洛谷P3338/LOJ2200/BZOJ3527[ZJOI2014]力(FFT)

首先看出$E_i=\frac{\sum\limits^{i-1}_{j=1}\frac{q_iq_j}{(i-j)^2}-\sum\limits^n_{j=i+1}\frac{q_iq_j}{(i-j)^2}}{q_i}=\sum\limits^{i-1}_{j=1}\frac{q_j}{(i-j)^2}-\sum\limits^n_{j=i+1}\frac{q_j}{(i-j)^2}$。

考虑设$t_i=\frac{1}{i^2}$,则$E_i=\sum\limits^{i-1}_{j=1}q_jt_{i-j}-\sum\limits^n_{j=i+1}q_jt_{j-i}$,再设$a_i=q_i,b_i=q_{n-i+1}$,则有$E_i=\sum\limits^{i-1}_{j=1}a_jt_{i-j}-\sum\limits^n_{j=n-i+1}b_{n-j+1}t_{j-i}$,注意到被减数是$a,t$的卷积,减数是$b,t$反向的卷积,FFT即可。

#include<cstdio>
#include<cmath>
const int N=270000;
const double pi=acos(-1.0);
double p[N];
int r[N],sz=1,l=0;
struct cnum{
    double x,y;
    cnum(){}
    cnum(double x):x(x){y=0;}
    cnum(double x,double y):x(x),y(y){}
    inline cnum operator +(cnum &b){return cnum(x+b.x,y+b.y);}
    inline cnum operator -(cnum &b){return cnum(x-b.x,y-b.y);}
    inline cnum operator *(cnum &b){return cnum(x*b.x-y*b.y,x*b.y+y*b.x);}
}a[N],b[N],c[N];
inline void FFT(cnum *a,short type){
    int i,j,M,R;
    cnum w,wn,t,tt;
    for(i=0;i<sz;++i)if(i<r[i]){t=a[i];a[i]=a[r[i]];a[r[i]]=t;}
    for(M=1;M<sz;M<<=1){
        wn=cnum(cos(pi/M),sin(pi/M)*type);
        for(i=0,R=M<<1;i<sz;i+=R){
            w=cnum(1,0);
            for(j=0;j<M;++j){
                t=a[i+j];tt=a[i+M+j]*w;
                a[i+j]=t+tt;a[i+M+j]=t-tt;
                w=w*wn;
            }
        }
    }
}
int main(){
    int n,i;
    double x;
    scanf("%d",&n);
    for(i=1;i<=n;++i)scanf("%lf",p+i);
    for(;sz<=(n<<1);sz<<=1)++l;
    for(i=0;i<sz;++i)r[i]=(r[i>>1]>>1)|((i&1)<<l-1);
    for(i=1;i<=n;++i){
        a[i]=cnum(p[i]);
        b[i]=cnum(p[n-i+1]);
        c[i]=cnum(1.0/i/i);
    }
    FFT(a,1);FFT(b,1);FFT(c,1);
    for(i=0;i<=sz;++i){a[i]=a[i]*c[i];b[i]=b[i]*c[i];}
    FFT(a,-1);FFT(b,-1);
    for(i=1;i<=n;++i)printf("%.3lf\n",(a[i].x-b[n-i+1].x)/sz);
    return 0;
}
View Code

 

posted @ 2019-08-15 16:32  wangyuchen  阅读(180)  评论(0编辑  收藏  举报