以前没写过这类题目
dp方程不难得到 f[i]=∑ f[j]*a[i-j]
这是卷积的形式,考虑用fft优化
虽然f[i]之前的值是未确定的,但是这里可以算贡献,用分治即可
具体的对于[l,r],先计算[l,mid]的f[],再计算f[l..mid]对f[mid+1..r]的贡献,最后计算f[mid+1..r]的值

1 #include<bits/stdc++.h> 2 #define pi acos(-1) 3 #define N 262150 4 using namespace std; 5 typedef complex<double> E; 6 7 const int mo=313; 8 E ta[N],tb[N]; 9 int f[N],a[N],r[N],n; 10 void fft(E *a,int n,int f) 11 { 12 for (int i=0; i<n; i++) 13 if (i<r[i]) swap(a[i],a[r[i]]); 14 for (int i=1; i<n; i<<=1) 15 { 16 E p(cos(pi/i),f*sin(pi/i)); 17 for (int j=0; j<n; j+=i<<1) 18 { 19 E w(1,0); 20 for (int k=0; k<i; k++) 21 { 22 E u=a[j+k],v=w*a[j+k+i]; 23 a[j+k]=u+v; 24 a[j+k+i]=u-v; 25 w*=p; 26 } 27 } 28 } 29 } 30 31 void work(int h,int t) 32 { 33 int m=t-h+1,mid=(h+t)>>1; 34 int n,l=0; 35 for (n=1; n<=m; n<<=1) l++; 36 for (int i=0; i<n; i++) 37 { 38 r[i]=(r[i>>1]>>1)|((i&1)<<(l-1)); 39 ta[i]=tb[i]=0; 40 } 41 for (int i=h; i<=mid; i++) ta[i-h]=f[i]; 42 for (int i=1; i<=m; i++) tb[i]=a[i]; 43 fft(ta,n,1); fft(tb,n,1); 44 for (int i=0; i<=n; i++) ta[i]*=tb[i]; 45 fft(ta,n,-1); 46 for (int i=mid+1; i<=t; i++) 47 f[i]=(f[i]+(int)(ta[i-h].real()/n+0.5))%mo; 48 } 49 50 void solve(int l,int r) 51 { 52 if (l==r) return; 53 int m=(l+r)>>1; 54 solve(l,m); 55 work(l,r); 56 solve(m+1,r); 57 } 58 59 int main() 60 { 61 scanf("%d",&n); 62 while (n) 63 { 64 for (int i=1; i<=n; i++) 65 { 66 scanf("%d",&a[i]); 67 a[i]%=mo; 68 } 69 memset(f,0,sizeof(f)); 70 f[0]=1; 71 solve(0,n); 72 printf("%d ",f[n]); 73 scanf("%d",&n); 74 } 75 }