InputThe first line of the input is a single integer T (T=5)T (T=5), indicating the number of testcases.
For each testcase, the first line contains one integer nn. The second line contains nnnon-negative integers, which mean the length of every section. If we denote the total length of all the sections as ss, we can guarantee that 0≤s≤500000≤s≤50000 and 1≤n≤1000001≤n≤100000.
OutputFor each testcase, print s+1s+1 lines. The single number in the ii-th line indicates the total pleasure JRY can get if he races all the ways of length i−1i−1.
Sample Input
2 3 1 2 3 4 0 1 2 3
Sample Output
0 1 1 3 0 2 3 1 3 1 6 0 2 7
数学问题 生成函数 FFT
给一个数列,若有一个数对(i,j)满足sum[i]-sum[j-1]==S,则得到i-(j-1)的收益,求S取0到[数列总和]的每一个值时,各自的全部收益。
神一样的构造解……
看到数据范围这么大,又是求所有方案的累计贡献,普通的方法显然难以奏效。这时候就要考虑生成函数了。
如果把这看成一个多项式问题,两元相乘时次数相加,系数相乘,那么让题目中的"定值"在指数上体现出来。
↑ ΣS <=50000,那么让x^i这一位存储S=i时的收益,那么应该计算出所有的 [i-(j-1)]*x^s ,即为路程为s时的收益
那么就要构造能得到 [i-(j-1)]*x^s 形式的项的多项式。
根据sum[i]-sum[j-1]==S可以有:
Σ([ai]*x^sum[i])*Σ(x^-(sum[j-1]) - Σ(x^sum[i])*Σ([a(j-1)]x^-(sum[j-1])
这样算卷积,指数部分得到sum[i]-sum[j-1],系数部分得到所有的(i-(j-1)),岂不美哉。
S取0的情况可以特判O(n)处理
传说FFT会爆精度,用了Long double以后成功AC
然后试了试NTT取超大模数强行算,对拍过了一些小数据,然而交上去TLE了
↑看到别人的NTT是可以过的,那就是我写的有问题,然而懒得改了先放着
FFT:
1 /*by SilverN*/ 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 #define LL long long 8 using namespace std; 9 const long double pi=acos(-1.0); 10 const int mxn=350021; 11 int read(){ 12 int x=0,f=1;char ch=getchar(); 13 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 14 while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} 15 return x*f; 16 } 17 struct com{ 18 long double x,y; 19 com operator + (const com b){return (com){x+b.x,y+b.y};} 20 com operator - (const com b){return (com){x-b.x,y-b.y};} 21 com operator * (const com b){return (com){x*b.x-y*b.y,x*b.y+y*b.x};} 22 }a[mxn],b[mxn],c[mxn]; 23 int N,l,rev[mxn]; 24 void FFT(com *a,int flag){ 25 int i,j,k; 26 for(i=0;i<N;i++)if(rev[i]>i)swap(a[rev[i]],a[i]); 27 for(i=1;i<N;i<<=1){ 28 com wn=(com){cos(pi/i),flag*sin(pi/i)}; 29 for(j=0;j<N;j+=(i<<1)){ 30 com w=(com){1,0}; 31 for(k=0;k<i;k++,w=w*wn){ 32 com x=a[j+k],y=w*a[j+k+i]; 33 a[j+k]=x+y; 34 a[i+j+k]=x-y; 35 } 36 } 37 } 38 if(flag==-1)for(i=0;i<N;i++)a[i].x/=N; 39 return; 40 } 41 int n,w[mxn]; 42 LL ans[mxn]; 43 int smm[mxn]; 44 void init(){ 45 n=read(); 46 LL cnt=0; 47 ans[0]=0; 48 for(int i=1;i<=n;i++){ 49 w[i]=read(); 50 smm[i]=smm[i-1]+w[i]; 51 if(!w[i]){//0 52 cnt++; 53 ans[0]+=cnt*(cnt+1)/2; 54 } 55 else cnt=0; 56 } 57 return; 58 } 59 int main(){ 60 int i,j; 61 int T=read(); 62 63 while(T--){ 64 init(); 65 // for(i=1;i<=n;i++)printf("%d ",smm[i]); 66 // printf("\n"); 67 memset(a,0,sizeof a); 68 memset(b,0,sizeof b); 69 memset(c,0,sizeof c); 70 int ed=smm[n]; 71 int m=ed<<1; 72 for(N=1,l=0;N<=m;N<<=1)l++; 73 for(i=0;i<N;i++){ 74 rev[i]=(rev[i>>1]>>1)|((i&1)<<(l-1)); 75 } 76 // 77 for(i=1;i<=n;i++){ 78 a[smm[i]].x+=i; 79 b[ed-smm[i-1]].x+=1; 80 } 81 /* 82 for(i=0;i<=ed;i++)printf("%.2Lf ",a[i].x); 83 printf("\n"); 84 for(i=0;i<=ed;i++)printf("%.2Lf ",b[i].x); 85 printf("\n"); 86 */ 87 FFT(a,1);FFT(b,1); 88 for(i=0;i<=N;i++) 89 c[i]=a[i]*b[i]; 90 FFT(c,-1); 91 memset(a,0,sizeof a); 92 memset(b,0,sizeof b); 93 for(i=1;i<=n;i++){ 94 a[smm[i]].x+=1; 95 b[ed-smm[i-1]].x+=i-1; 96 } 97 FFT(a,1);FFT(b,1); 98 for(i=0;i<=N;i++){ 99 a[i]=a[i]*b[i]; 100 } 101 FFT(a,-1); 102 for(i=0;i<=N;i++)c[i]=c[i]-a[i]; 103 printf("%lld\n",ans[0]); 104 for(i=1;i<=ed;i++){ 105 printf("%lld\n",(LL)(c[i+ed].x+0.5)); 106 } 107 } 108 return 0; 109 }
TLE的NTT
1 /*by SilverN*/ 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 #define LL long long 8 using namespace std; 9 //const LL P=(1LL<<47)*7*4451+1; 10 const LL P=479*(1<<21)+1; 11 //const LL mod=479*(1<<21)+1; 12 const int mxn=130021; 13 int read(){ 14 int x=0,f=1;char ch=getchar(); 15 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 16 while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} 17 return x*f; 18 } 19 LL a[mxn],b[mxn],c[mxn]; 20 int N,l; 21 LL mul(LL x,LL y) { 22 LL res=0; 23 while(y){ 24 if(y&1)res=(res+x)%P; 25 x=(x<<1)%P; 26 y>>=1; 27 } 28 return res; 29 } 30 LL ksm(LL a,LL k){ 31 LL res=1; 32 while(k){ 33 if(k&1)res=mul(res,a); 34 a=mul(a,a); 35 k>>=1; 36 } 37 return res; 38 } 39 int rev[mxn]; 40 void NTT(LL *a,int flag){ 41 int i,j,k; 42 for(i=0;i<N;i++)if(rev[i]>i)swap(a[rev[i]],a[i]); 43 for(i=1;i<N;i<<=1){ 44 LL gn=ksm(3,(P-1)/(i<<1)); 45 int p=i<<1; 46 for(j=0;j<N;j+=p){ 47 LL g=1; 48 for(k=0;k<i;k++,g=mul(g,gn)){ 49 LL x=a[j+k],y=mul(g,a[j+k+i]); 50 a[j+k]=(x+y)%P; 51 a[i+j+k]=(x-y+P)%P; 52 } 53 } 54 } 55 if(flag==-1){ 56 reverse(a+1,a+N); 57 LL inv=ksm(N,P-2); 58 for(i=0;i<N;i++)a[i]=mul(a[i],inv)%P; 59 } 60 return; 61 } 62 int n,w[mxn]; 63 LL ans[mxn]; 64 int smm[mxn]; 65 void init(){ 66 n=read(); 67 LL cnt=0; 68 ans[0]=0; 69 for(int i=1;i<=n;i++){ 70 w[i]=read(); 71 smm[i]=smm[i-1]+w[i]; 72 if(!w[i]){//0 73 cnt++; 74 ans[0]+=cnt*(cnt+1)/2; 75 } 76 else cnt=0; 77 } 78 return; 79 } 80 int main(){ 81 int i,j; 82 int T=read(); 83 while(T--){ 84 init(); 85 memset(a,0,sizeof a); 86 memset(b,0,sizeof b); 87 memset(c,0,sizeof c); 88 int ed=smm[n]; 89 int m=ed<<1; 90 for(N=1,l=0;N<=m;N<<=1)l++; 91 for(i=0;i<N;i++){ 92 rev[i]=(rev[i>>1]>>1)|((i&1)<<(l-1)); 93 } 94 // 95 for(i=1;i<=n;i++){ 96 a[smm[i]]+=i; 97 b[ed-smm[i-1]]+=1; 98 } 99 100 NTT(a,1);NTT(b,1); 101 // for(i=0;i<=N;i++)printf("%lld ",a[i]);printf("\n"); 102 for(i=0;i<=N;i++) 103 c[i]=mul(a[i],b[i])%P; 104 NTT(c,-1); 105 memset(a,0,sizeof a); 106 memset(b,0,sizeof b); 107 for(i=1;i<=n;i++){ 108 a[smm[i]]+=1; 109 b[ed-smm[i-1]]+=i-1; 110 } 111 NTT(a,1);NTT(b,1); 112 for(i=0;i<=N;i++){ 113 a[i]=mul(a[i],b[i])%P; 114 } 115 NTT(a,-1); 116 for(i=0;i<=N;i++)c[i]=(c[i]-a[i]+P)%P; 117 printf("%lld\n",ans[0]); 118 for(i=1;i<=ed;i++){ 119 printf("%lld\n",c[i+ed]); 120 } 121 } 122 return 0; 123 }