【最短路】[JZOJ5864] 很多序列
阿新 • • 發佈:2018-11-10
Description
Solution
這題咋一看。。NOIP2017D1T1的陰影仍然揮之不去。。。
找了一波規律,數論推了一波,什麼都沒有。。
事實上這題是道最短路題。。
觀察資料範圍,發現它比較獵奇
首先n=2我們直接用公式就是a*b-ab,去了NOIP2017都知道
最小的那個數很小,我們考慮在模x1下來做,對於模x1=p的某個位置,最小值以上都可以通過+x1來得到
問題就轉化成模x1=p的某個位置最小能用另外幾個數表示的數是什麼
這就可以直接做最短路了。。。
Code
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fod(i,a,b) for(int i=a;i>=b;i--)
#define N 1005
#define LL long long
using namespace std;
LL a[6],f[N];
bool bz[N];
int n,d[100*N];
void spfa()
{
d[1 ]=0;
memset(f,107,sizeof(f));
int l=0,r=1;
f[0]=0;
while(l<r)
{
int k=d[++l];
fo(j,2,n)
{
int p=(k+a[j])%a[1];
if(f[p]>f[k]+a[j])
{
f[p]=f[k]+a[j];
if(!bz[p])
{
bz[p]=1 ;
d[++r]=p;
if(f[p]<f[d[l+1]]) swap(d[l+1],d[r]);
}
}
}
bz[k]=0;
}
}
int main()
{
cin>>n;
LL mx=0;
fo(i,1,n) scanf("%lld",&a[i]);
LL v=a[1]*a[2]-a[1]-a[2];
if(n==2)
{
printf("%lld\n",v);
return 0;
}
spfa();
v=1;
fo(i,0,a[1]-1) v=max(v,f[i]-a[1]);
printf("%lld\n",v);
}