题面
传送门
思路
把要求的公式列出来:
$E_i=\frac{F_i}{q_i}=\sum_{j=1}^i\frac{q_j}{\left(i-j\right)^2}-\sum_{j=i+1}^n\frac{q_j}{\left(i-j\right)^2}$
令$x_i=\frac1{i^2}$,那么
$E_i=\sum_{j=1}^iq_jx_{i-j}-\sum_{j=i+1}^nq_jx_{j-i}$
那我们再令$p_i=q_{n-i+1}$,那么
$E_i=\sum_{j=1}^iq_jx_{i-j}-\sum_{j=i+1}^np_{n-j}x_{j-i}$
此时我们发现式子的左侧和右侧都是一个卷积的形式
那么,我们就可以用FFT来维护这个过程了
将数列$q_i$,$p_i$,$x_i$作为多项式$A$,$B$,$C$的系数
将他们用fft乘起来,得到的$A\ast C$,$B\ast C$的系数做差,就是$E_i$的值
Code:
#include
#include
#include
#include
#include
struct complex{
double x,y;
complex(double xx=0,double yy=0){x=xx;y=yy;}
complex operator +(const complex &b){return complex(b.x+x,b.y+y);}
complex operator -(const complex &b){return complex(-b.x+x,-b.y+y);}
complex operator *(const complex &b){return complex(x*b.x-y*b.y,x*b.y+y*b.x);}
}A[410010],B[410010],C[410010];
const double pi=acos(-1.0);
int n,limit=1,cnt=0,r[410010];
void fft(complex *a,double type){
int i,mid,j,k,R;complex w,wn,x,y;
for(i=0;i>1]>>1)|((i&1)<<(cnt-1)));
fft(A,1);fft(B,1);fft(C,1);
for(i=0;i<=limit;i++) A[i]=A[i]*C[i],B[i]=B[i]*C[i];
fft(A,-1);fft(B,-1);
for(i=0;i<=limit;i++) A[i].x/=limit,B[i].x/=limit;
for(i=1;i<=n;i++) printf("%.4lf\n",-B[n+1-i].x+A[i].x);
}