[ZJOI2014][bzoj3527]力 [FFT]

题面

传送门

思路

把要求的公式列出来:

$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);
}

转载于:https://www.cnblogs.com/dedicatus545/p/8830852.html

你可能感兴趣的:([ZJOI2014][bzoj3527]力 [FFT])