1. 程式人生 > >【最短路】[JZOJ5864] 很多序列

【最短路】[JZOJ5864] 很多序列

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); }