洛谷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即可。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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; }