hdu Shell Necklace 5730 分治FFT

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
",f[n]);
73     }
74 }
原文地址:https://www.cnblogs.com/fengzhiyuan/p/8625638.html