洛谷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}^n\frac{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求出两个卷积,然后做差就可以了

 //minamoto
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=3e5+;const double Pi=acos(-);
struct complex{
double x,y;
complex(double xx=,double yy=){x=xx,y=yy;}
inline complex operator +(complex b){return complex(x+b.x,y+b.y);}
inline complex operator -(complex b){return complex(x-b.x,y-b.y);}
inline complex operator *(complex b){return complex(x*b.x-y*b.y,x*b.y+y*b.x);}
}A[N],B[N],C[N];
int n,m,l,r[N],limit=;
void FFT(complex *A,int type){
for(int i=;i<limit;++i)
if(i<r[i]) swap(A[i],A[r[i]]);
for(int mid=;mid<limit;mid<<=){
complex Wn(cos(Pi/mid),type*sin(Pi/mid));
for(int R=mid<<,j=;j<limit;j+=R){
complex w(,);
for(int k=;k<mid;++k,w=w*Wn){
complex x=A[j+k],y=w*A[j+mid+k];
A[j+k]=x+y,A[j+mid+k]=x-y;
}
}
}
}
int main(){
// freopen("testdata.in","r",stdin);
scanf("%d",&n);
while(limit<=n*) limit<<=,++l;
for(int i=;i<=limit;++i) r[i]=(r[i>>]>>)|((i&)<<(l-));
for(int i=;i<=n;++i)
scanf("%lf",&A[i].x),B[n+-i].x=A[i].x,C[i].x=1.0/i/i;
FFT(A,),FFT(B,),FFT(C,);
for(int i=;i<=limit;++i) A[i]=A[i]*C[i],B[i]=B[i]*C[i];
FFT(A,-),FFT(B,-);
for(int i=;i<=limit;++i) A[i].x/=limit,B[i].x/=limit;
for(int i=;i<=n;++i)
printf("%.3lf\n",A[i].x-B[n-i+].x);
return ;
}
上一篇:python中常用的导包的方法和常用的库


下一篇:MySQL 8.0.13 下载安装教程