以前没写过这类题目

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\n",f[n]);
73         scanf("%d",&n);
74     }
75 }
View Code

 

posted on 2017-03-17 14:53  acphile  阅读(170)  评论(0编辑  收藏  举报