洛谷P3338 [ZJOI2014]力(FFT)

传送门

题目要求$$E_i=frac{F_i}{q_i}=sum_{j=1}^{i-1}frac{q_j}{(i-j)^2}-sum_{j=i+1}^nfrac{q_j}{(j-i)^2}$$

令$x_i=frac{1}{i^2}$,则有$$E_i=sum_{j=1}^{i-1} q_j x_{i-j}-sum_{j=i+1}^n q_j x_{j-i}$$

令$p_i=q_{n-i+1}$,则有$$E_i=sum_{j=1}^{i-1} q_j x_{i-j}-sum_{j=i+1}^n p_{n-j+1} x_{j-i}$$

那么不难发现这两个都是卷积(然而我连卷积是啥都不知道)

简单来讲,两个多项式的卷积$(f*g)(n)=sum_{i=0}^nf(i)g(n-i)$,可以发现这个和多项式乘法的某一项系数的值的求法相同

然后只要用FFT求出两个卷积,然后做差就可以了

 1 //minamoto
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<algorithm>
 5 using namespace std;
 6 const int N=3e5+5;const double Pi=acos(-1);
 7 struct complex{
 8     double x,y;
 9     complex(double xx=0,double yy=0){x=xx,y=yy;}
10     inline complex operator +(complex b){return complex(x+b.x,y+b.y);}
11     inline complex operator -(complex b){return complex(x-b.x,y-b.y);}
12     inline complex operator *(complex b){return complex(x*b.x-y*b.y,x*b.y+y*b.x);}
13 }A[N],B[N],C[N];
14 int n,m,l,r[N],limit=1;
15 void FFT(complex *A,int type){
16     for(int i=0;i<limit;++i)
17     if(i<r[i]) swap(A[i],A[r[i]]);
18     for(int mid=1;mid<limit;mid<<=1){
19         complex Wn(cos(Pi/mid),type*sin(Pi/mid));
20         for(int R=mid<<1,j=0;j<limit;j+=R){
21             complex w(1,0);
22             for(int k=0;k<mid;++k,w=w*Wn){
23                 complex x=A[j+k],y=w*A[j+mid+k];
24                 A[j+k]=x+y,A[j+mid+k]=x-y;
25             }
26         }
27     }
28 }
29 int main(){
30 //    freopen("testdata.in","r",stdin);
31     scanf("%d",&n);
32     while(limit<=n*2) limit<<=1,++l;
33     for(int i=0;i<=limit;++i) r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
34     for(int i=1;i<=n;++i)
35     scanf("%lf",&A[i].x),B[n+1-i].x=A[i].x,C[i].x=1.0/i/i;
36     FFT(A,1),FFT(B,1),FFT(C,1);
37     for(int i=0;i<=limit;++i) A[i]=A[i]*C[i],B[i]=B[i]*C[i];
38     FFT(A,-1),FFT(B,-1);
39     for(int i=0;i<=limit;++i) A[i].x/=limit,B[i].x/=limit;
40     for(int i=1;i<=n;++i)
41     printf("%.3lf
",A[i].x-B[n-i+1].x);
42     return 0;
43 }
原文地址:https://www.cnblogs.com/bztMinamoto/p/9742771.html