HDU5307 He is Flying

JRY wants to drag racing along a long road. There are  nn sections on the road, the ii-th section has a non-negative integer length sisi. JRY will choose some continuous sections to race (at an unbelievable speed), so there are totally n(n+1)2n(n+1)2 different ways for him to ride. If JRY rides across from the ii-th section to the jj-th section, he would gain ji+1j−i+1 pleasure. Now JRY wants to know, if he tries all the ways whose length is ss, what's the total pleasure he can get. Please be aware that in the problem, the length of one section could be zero, which means that the length is so trivial that we can regard it as 00.

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 0s500000≤s≤50000 and 1n1000001≤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 i1i−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 }

 

转载于:https://www.cnblogs.com/SilverNebula/p/6528952.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值