您的位置:首页 > 其它

HDU5307 He is Flying

2017-03-10 09:16 253 查看
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 j−i+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 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:

/*by SilverN*/
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long
using namespace std;
const long double pi=acos(-1.0);
const int mxn=350021;
int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
struct com{
long double x,y;
com operator + (const com b){return (com){x+b.x,y+b.y};}
com operator - (const com b){return (com){x-b.x,y-b.y};}
com operator * (const com b){return (com){x*b.x-y*b.y,x*b.y+y*b.x};}
}a[mxn],b[mxn],c[mxn];
int N,l,rev[mxn];
void FFT(com *a,int flag){
int i,j,k;
for(i=0;i<N;i++)if(rev[i]>i)swap(a[rev[i]],a[i]);
for(i=1;i<N;i<<=1){
com wn=(com){cos(pi/i),flag*sin(pi/i)};
for(j=0;j<N;j+=(i<<1)){
com w=(com){1,0};
for(k=0;k<i;k++,w=w*wn){
com x=a[j+k],y=w*a[j+k+i];
a[j+k]=x+y;
a[i+j+k]=x-y;
}
}
}
if(flag==-1)for(i=0;i<N;i++)a[i].x/=N;
return;
}
int n,w[mxn];
LL ans[mxn];
int smm[mxn];
void init(){
n=read();
LL cnt=0;
ans[0]=0;
for(int i=1;i<=n;i++){
w[i]=read();
smm[i]=smm[i-1]+w[i];
if(!w[i]){//0
cnt++;
ans[0]+=cnt*(cnt+1)/2;
}
else cnt=0;
}
return;
}
int main(){
int i,j;
int T=read();

while(T--){
init();
//        for(i=1;i<=n;i++)printf("%d ",smm[i]);
//        printf("\n");
memset(a,0,sizeof a);
memset(b,0,sizeof b);
memset(c,0,sizeof c);
int ed=smm
;
int m=ed<<1;
for(N=1,l=0;N<=m;N<<=1)l++;
for(i=0;i<N;i++){
rev[i]=(rev[i>>1]>>1)|((i&1)<<(l-1));
}
//
for(i=1;i<=n;i++){
a[smm[i]].x+=i;
b[ed-smm[i-1]].x+=1;
}
/*
for(i=0;i<=ed;i++)printf("%.2Lf ",a[i].x);
printf("\n");
for(i=0;i<=ed;i++)printf("%.2Lf ",b[i].x);
printf("\n");
*/
FFT(a,1);FFT(b,1);
for(i=0;i<=N;i++)
c[i]=a[i]*b[i];
FFT(c,-1);
memset(a,0,sizeof a);
memset(b,0,sizeof b);
for(i=1;i<=n;i++){
a[smm[i]].x+=1;
b[ed-smm[i-1]].x+=i-1;
}
FFT(a,1);FFT(b,1);
for(i=0;i<=N;i++){
a[i]=a[i]*b[i];
}
FFT(a,-1);
for(i=0;i<=N;i++)c[i]=c[i]-a[i];
printf("%lld\n",ans[0]);
for(i=1;i<=ed;i++){
printf("%lld\n",(LL)(c[i+ed].x+0.5));
}
}
return 0;
}

 

TLE的NTT

 

/*by SilverN*/
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long
using namespace std;
//const LL P=(1LL<<47)*7*4451+1;
const LL P=479*(1<<21)+1;
//const LL mod=479*(1<<21)+1;
const int mxn=130021;
int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
LL a[mxn],b[mxn],c[mxn];
int N,l;
LL mul(LL x,LL y) {
LL res=0;
while(y){
if(y&1)res=(res+x)%P;
x=(x<<1)%P;
y>>=1;
}
return res;
}
LL ksm(LL a,LL k){
LL res=1;
while(k){
if(k&1)res=mul(res,a);
a=mul(a,a);
k>>=1;
}
return res;
}
int rev[mxn];
void NTT(LL *a,int flag){
int i,j,k;
for(i=0;i<N;i++)if(rev[i]>i)swap(a[rev[i]],a[i]);
for(i=1;i<N;i<<=1){
LL gn=ksm(3,(P-1)/(i<<1));
int p=i<<1;
for(j=0;j<N;j+=p){
LL g=1;
for(k=0;k<i;k++,g=mul(g,gn)){
LL x=a[j+k],y=mul(g,a[j+k+i]);
a[j+k]=(x+y)%P;
a[i+j+k]=(x-y+P)%P;
}
}
}
if(flag==-1){
reverse(a+1,a+N);
LL inv=ksm(N,P-2);
for(i=0;i<N;i++)a[i]=mul(a[i],inv)%P;
}
return;
}
int n,w[mxn];
LL ans[mxn];
int smm[mxn];
void init(){
n=read();
LL cnt=0;
ans[0]=0;
for(int i=1;i<=n;i++){
w[i]=read();
smm[i]=smm[i-1]+w[i];
if(!w[i]){//0
cnt++;
ans[0]+=cnt*(cnt+1)/2;
}
else cnt=0;
}
return;
}
int main(){
int i,j;
int T=read();
while(T--){
init();
memset(a,0,sizeof a);
memset(b,0,sizeof b);
memset(c,0,sizeof c);
int ed=smm
;
int m=ed<<1;
for(N=1,l=0;N<=m;N<<=1)l++;
for(i=0;i<N;i++){
rev[i]=(rev[i>>1]>>1)|((i&1)<<(l-1));
}
//
for(i=1;i<=n;i++){
a[smm[i]]+=i;
b[ed-smm[i-1]]+=1;
}

NTT(a,1);NTT(b,1);
//        for(i=0;i<=N;i++)printf("%lld ",a[i]);printf("\n");
for(i=0;i<=N;i++)
c[i]=mul(a[i],b[i])%P;
NTT(c,-1);
memset(a,0,sizeof a);
memset(b,0,sizeof b);
for(i=1;i<=n;i++){
a[smm[i]]+=1;
b[ed-smm[i-1]]+=i-1;
}
NTT(a,1);NTT(b,1);
for(i=0;i<=N;i++){
a[i]=mul(a[i],b[i])%P;
}
NTT(a,-1);
for(i=0;i<=N;i++)c[i]=(c[i]-a[i]+P)%P;
printf("%lld\n",ans[0]);
for(i=1;i<=ed;i++){
printf("%lld\n",c[i+ed]);
}
}
return 0;
}

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: