HDU 5307 He is Flying 构造多项式+FFT

来源:互联网 发布:2017mac设置iphone铃声 编辑:程序博客网 时间:2024/06/05 21:08
题意:n个点 每个点价值为v[i],区间[l,r]的长度为r-l+1 区间价值为该区间内所有v[i]之和.

n<=1e5,v[i]累加和s<=5e4. 问区间价值为x时,这些区间长度的累加和. x=0,1,2...s.

答案:res[s[i]-s[j-1]]+=i-j+1 s[i]为前缀和i .O(n^2) TLE...

参考 S肯定也要指数,系数要体现和为S的区间的长度,则用两个前缀相减来表示



构造多项式:(ixsi)(xsi1)(xsi)((i1)xsi1).






 


最后X^S的系数也就是要求的答案

#include <bits/stdc++.h>using namespace std;typedef long long ll;typedef long double ld;const int N=1e5+5,M=(1<<17)+5;const ld pi=acos(-1.0);int sum[N],rev[M];struct C{    ld real,imag;    C(ld real=0,ld imag=0):real(real),imag(imag){}    friend C operator +(C A,C B){        return C(A.real+B.real,A.imag+B.imag);    }    friend C operator -(C A,C B){        return C(A.real-B.real,A.imag-B.imag);    }    friend C operator *(C A,C B){        return C(A.real*B.real-A.imag*B.imag,A.imag*B.real+A.real*B.imag);    }}A[M],B[M],ans[2][M];void rd(int &res){    res=0;    char c;    while(c=getchar(),c<48);    do res=(res<<3)+(res<<1)+(c^48);        while(c=getchar(),c>47);}void FFT(C *arr,int n,int flag){    for(int i=0;i<n;++i)        if(i<rev[i])            swap(arr[i],arr[rev[i]]);    for(int m=2;m<=n;m<<=1){        C wm(cos(2*pi/m),flag*sin(2*pi/m));        for(int i=0;i<n;i+=m){            C w(1,0);            for(int j=0;j<m>>1;++j,w=w*wm){                C x=arr[i+j],y=w*arr[i+j+(m>>1)];                arr[i+j]=x+y;                arr[i+j+(m>>1)]=x-y;            }        }    }}void calc_FFT(int n,bool id){    int _n=n,m=n<<1,S=0;    for(n=1;n<=m;n<<=1,++S);    rev[0]=0;    for(int i=1;i<n;++i)        rev[i]=(rev[i>>1]>>1)|((i&1)<<(S-1));    for(int i=_n+1;i<n;++i)        A[i]=B[i]=0;    FFT(A,n,1);    FFT(B,n,1);    for(int i=0;i<n;++i)        ans[id][i]=A[i]*B[i];    FFT(ans[id],n,-1);    for(int i=0;i<=m;++i)        ans[id][i].real/=n;}void solve(){ll ans0=0;int n;scanf("%d",&n);sum[0]=0;for(int i=1,v,cnt=0;i<=n;i++){scanf("%d",&v),sum[i]=sum[i-1]+v;if(v==0){++cnt;ans0+=1ll*cnt*(cnt+1)/2;}elsecnt=0;}printf("%I64d\n",ans0);for(int i=0;i<=sum[n];i++)A[i]=B[i]=0;for(int i=1;i<=n;i++){A[sum[i]].real+=i;B[-sum[i-1]+sum[n]].real+=1;//¸ºÏµÊýÀëÉ¢»¯ }calc_FFT(sum[n],0);for(int i=0;i<=sum[n];++i)    A[i]=B[i]=0;        for(int i=1;i<=n;++i){        A[sum[i]].real+=1;        B[-sum[i-1]+sum[n]].real+=i-1;    }    calc_FFT(sum[n],1);//1 id    for(int i=1;i<=sum[n];i++)    printf("%I64d\n",(ll)(ans[0][i+sum[n]].real-ans[1][i+sum[n]].real+0.5));}int main(){int T;cin>>T;while(T--)solve();return 0;}


构造多项式:(ixsi)(xsi1)(xsi)((i1)xsi1).






 
原创粉丝点击