Description
Perhaps the sea‘s definition of a shell is the pearl. However, in my view, a shell necklace with n beautiful shells contains the most sincere feeling for my best lover Arrietty, but even that is not enough.
Suppose the shell necklace is a sequence of shells (not a chain end to end). Considering i continuous shells in the shell necklace, I know that there exist different schemes to decorate the i shells together with one declaration of love.
I want to decorate all the shells with some declarations of love and decorate each shell just one time. As a problem, I want to know the total number of schemes.
Input
There are multiple test cases(no more than 20 cases and no more than 1 in extreme case), ended by 0.
For each test cases, the first line contains an integer n, meaning the number of shells in this shell necklace, where 1≤n≤105. Following line is a sequence with n non-negative integer a1,a2,…,an, and ai≤107 meaning the number of schemes to decorate i continuous shells together with a declaration of love.
Output
For each test case, print one line containing the total number of schemes module 313(Three hundred and thirteen implies the march 13th, a special and purposeful day).
Sample Input
3
1 3 7
4
2 2 2 2
0
Sample Output
14
54
题意:就是给定长度为n,然后长度为1-n的珠子有a[i]种,问拼成长度n的方案数,每种珠子有无限个。
题解:f[i]设为拼成i的方案数,发现转移时f[i]=∑f[j]*a[i-j]+a[i] (1<=j<i)发现是个卷积的形式。
如何去优化。
去分治解决,设 l,mid的已经处理好了,那么,考虑l,mid对mid+1,r的贡献,
对于l,mid的贡献部分做卷积运算,得出其贡献,加到mid,r中。
这个过程就是CDQ的过程。
1 #include<cstring> 2 #include<iostream> 3 #include<cstdio> 4 #include<algorithm> 5 #include<cmath> 6 7 #define N 200007 8 #define pi acos(-1) 9 #define mod 313 10 using namespace std; 11 inline int read() 12 { 13 int x=0,f=1;char ch=getchar(); 14 while(!isdigit(ch)){if(ch=='-')f=1;ch=getchar();} 15 while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} 16 return x*f; 17 } 18 19 int n,num,L; 20 int a[N],rev[N],f[N]; 21 struct comp 22 { 23 double r,v; 24 comp(double _r=0,double _v=0){r=_r;v=_v;} 25 friend inline comp operator+(comp x,comp y){return comp(x.r+y.r,x.v+y.v);} 26 friend inline comp operator-(comp x,comp y){return comp(x.r-y.r,x.v-y.v);} 27 friend inline comp operator*(comp x,comp y){return comp(x.r*y.r-x.v*y.v,x.r*y.v+x.v*y.r);} 28 }x[N],y[N]; 29 30 void FFT(comp *a,int f) 31 { 32 for (int i=1;i<num;i++) 33 if (i<rev[i]) swap(a[i],a[rev[i]]); 34 for (int i=1;i<num;i<<=1) 35 { 36 comp wn=comp(cos(pi/i),f*sin(pi/i)); 37 for (int j=0;j<num;j+=(i<<1)) 38 { 39 comp w=comp(1,0); 40 for (int k=0;k<i;k++,w=w*wn) 41 { 42 comp x=a[j+k],y=w*a[j+k+i]; 43 a[j+k]=x+y,a[j+k+i]=x-y; 44 } 45 } 46 } 47 if (f==-1) for (int i=0;i<num;i++) a[i].r/=num; 48 } 49 void CDQ(int l,int r) 50 { 51 if (l==r) {f[l]=(f[l]+a[l])%mod;return;} 52 int mid=(l+r)>>1; 53 CDQ(l,mid); 54 L=0;for (num=1;num<=(r-l+1);num<<=1,L++);if (L) L--; 55 for (int i=0;i<num;i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<L); 56 for (int i=1;i<num;i++) x[i]=y[i]=comp(0,0); 57 for (int i=l;i<=mid;i++) x[i-l]=comp(f[i],0); 58 for (int i=1;i<=r-l;i++) y[i-1]=comp(a[i],0); 59 FFT(x,1);FFT(y,1); 60 for (int i=0;i<num;i++) x[i]=x[i]*y[i]; 61 FFT(x,-1); 62 for (int i=mid+1;i<=r;i++) 63 (f[i]+=x[i-l-1].r+0.5)%=mod; 64 CDQ(mid+1,r); 65 } 66 int main() 67 { 68 while(~scanf("%d",&n)&&n) 69 { 70 for (int i=1;i<=n;i++) a[i]=read()%mod,f[i]=0; 71 CDQ(1,n); 72 printf("%d\n",f[n]); 73 } 74 }