Shell Necklace
Time Limit: 16000/8000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1587 Accepted Submission(s): 721
Problem 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.
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.
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
Hint
For the first test case in Sample Input, the Figure 1 provides all schemes about it. The total number of schemes is 1 + 3 + 3 + 7 = 14.
Author
HIT
Source
递推式很显然
然而这个东西虽然是卷积 但显然不能直接FFT
所以呢 分治FFT/NTT !
具体来讲就是
每次处理区间 [l,r]
先处理 [l,mid]
对于 [l,mid] 已求出真值 处理其对 [mid+1,r] 取值的影响
之后再处理 [mid+1,r]
#include<cmath>
#include<ctime>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<string>
#include<bitset>
#include<queue>
#include<map>
#include<set>
using namespace std;
typedef double db;
typedef long long ll;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){x=10*x+ch-'0';ch=getchar();}
return x*f;
}
void print(ll x)
{if(x<0)putchar('-'),x=-x;if(x>=10)print(x/10);putchar(x%10+'0');}
const int N=300100,mod=313;
const db pi=acos(-1);
struct cp
{
db real,image;
friend cp operator +(const cp &x,const cp &y)
{return (cp){x.real+y.real,x.image+y.image};}
friend cp operator -(const cp &x,const cp &y)
{return (cp){x.real-y.real,x.image-y.image};}
friend cp operator *(const cp &x,const cp &y)
{return (cp){x.real*y.real-x.image*y.image,x.image*y.real+x.real*y.image};}
}A[N],B[N];
int R[N];
void fft(cp *x,int lim,int opt)
{
register int i,j,k,m;
for(i=0;i<lim;++i)
if(R[i]<i)
swap(x[i],x[R[i]]);
for(m=2;m<=lim;m<<=1)
{
k=m>>1;
cp wn=(cp){cos(2*pi*opt/m),sin(2*pi*opt/m)};
for(i=0;i<lim;i+=m)
{
cp w=(cp){1,0},tmp;
for(j=0;j<k;++j,w=w*wn)
{
tmp=x[i+j+k]*w;
x[i+j+k]=x[i+j]-tmp;
x[i+j]=x[i+j]+tmp;
}
}
}
if(opt==-1)
for(i=0;i<lim;++i)
x[i].real=x[i].real/lim+0.3;
}
int n;
int a[N];
ll f[N];
void cdq(int l,int r)
{
if(l==r) return ;
int mid((l+r)>>1);
cdq(l,mid);
int len(r-l),lim(1);
while(lim<=(len+mid-l)) lim<<=1;
for(int i=0;i<lim;++i)
R[i]=(i&1)*(lim>>1)+(R[i>>1]>>1),
A[i].real=A[i].image=B[i].real=B[i].image=0;
for(int i=l;i<=mid;++i) A[i-l].real=f[i];
for(int i=0;i<=len;++i) B[i].real=a[i];
fft(A,lim,1);fft(B,lim,1);
for(int i=0;i<lim;++i) A[i]=A[i]*B[i];
fft(A,lim,-1);
for(int i=mid+1;i<=r;++i)
(f[i]+=floor(A[i-l].real))%=mod;
cdq(mid+1,r);
}
int main()
{
register int i;
while(1)
{
n=read();
if(!n) break;
for(i=1;i<=n;++i)
a[i]=read()%mod;
f[0]=1;
cdq(0,n);
print(f[n]);
putchar('\n');
for(i=0;i<=n;++i) f[i]=0;
}
return 0;
}