【BZOJ3527】【ZJOI2014】力

时间:2021-11-14 23:06:16

"FFT还不是随手写?"我终于能说这样的话了இwஇ

原题:

给出n个数qi,给出Fj的定义如下:
【BZOJ3527】【ZJOI2014】力
令Ei=Fi/qi,求Ei.
FFT嘛,直接推公式
【BZOJ3527】【ZJOI2014】力

然后就变成俩卷积了,FFT即可

代码:

 #include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int rd(){int z=,mk=; char ch=getchar();
while(ch<''||ch>''){if(ch=='-')mk=-; ch=getchar();}
while(ch>=''&&ch<=''){z=(z<<)+(z<<)+ch-''; ch=getchar();}
return z*mk;
}
struct cp{
double r,i;
cp(double _r=,double _i=): r(_r),i(_i){}
cp operator+(cp x){return cp(r+x.r,i+x.i);}
cp operator-(cp x){return cp(r-x.r,i-x.i);}
cp operator*(cp x){return cp(r*x.r-i*x.i,r*x.i+i*x.r);}
};
int n;
cp a[],a_[],b[],tmp[],_x,_y;
cp e[],e_[];
int rvs[],dg[],N,L;
void fft(cp x[],int mk){
for(int i=;i<N;++i) tmp[i]=x[rvs[i]];
for(int i=;i<N;++i) x[i]=tmp[i];
for(int i=;i<=N;i<<=){
cp wn(cos(*M_PI/i),mk*sin(*M_PI/i));
for(int k=;k<N;k+=i){
cp w(,);
for(int j=k;j<k+(i>>);++j){
_x=x[j],_y=x[j+(i>>)]*w;
x[j]=_x+_y,x[j+(i>>)]=_x-_y;
w=w*wn;
}
}
}
if(mk==-) for(int i=;i<N;++i) x[i].r/=N;
}
int main(){//freopen("ddd.in","r",stdin);
cin>>n; n--;
double x;
for(int i=;i<=n;++i) scanf("%lf",&x),a[i]=cp(x);
for(int i=;i<=n;++i) a_[i]=a[n-i];
for(N=,L=;N<=(n+);N<<=,++L); N<<=,++L;
for(int i=;i<N;++i){
for(int j=i,k=;j;j>>=,++k) dg[k]=j&;
for(int j=;j<L;++j) rvs[i]=(rvs[i]<<)|dg[j];
}
for(int i=;i<=n;++i) b[i]=cp((double)/i/i);
fft(a,),fft(a_,),fft(b,);
for(int i=;i<N;++i) e[i]=a[i]*b[i];
for(int i=;i<N;++i) e_[i]=a_[i]*b[i];
fft(e,-),fft(e_,-);
for(int i=;i<=n;++i) printf("%.3lf\n",e[i].r-e_[n-i].r);
return ;
}