題目概述
給出
解題報告
FFT其實是在求向量卷積,形式是這樣的:
然後我們觀察題目裏給的式子,會發現
爲了方便,定義
左邊已經是卷積的形式了,但是右邊還比較奇怪,我們先把
爲了把右邊變成卷積,構造
所以用FFT求卷積,然後就可以快速得到
示例程序
#include<cstdio>
#include<cmath>
#include<algorithm>
#define fr first
#define sc second
#define mp make_pair
using namespace std;
typedef double DB;typedef pair<DB,DB> C;
const int maxn=262144;const double pi=acos(-1);
int n,m,R[maxn+5];C f[maxn+5],F[maxn+5],g[maxn+5];
inline int Rev(int x,int len){
static int buf[31];for (int i=0;i<len;i++) buf[i]=x&1,x>>=1;
for (int i=0;i<len;i++) x=x<<1|buf[i];return x;
}
C operator + (const C &a,const C &b) {return mp(a.fr+b.fr,a.sc+b.sc);}
C operator - (const C &a,const C &b) {return mp(a.fr-b.fr,a.sc-b.sc);}
C operator * (const C &a,const C &b) {return mp(a.fr*b.fr-a.sc*b.sc,a.fr*b.sc+a.sc*b.fr);}
inline void FFT(C *a,int n,int f){
for (int i=0;i<n;i++) if (i<R[i]) swap(a[i],a[R[i]]);
for (int k=1;k<n;k<<=1){
C w=mp(1,0),wn=mp(cos(pi/k),sin(f*pi/k)),x,y;
for (int i=0;i<n;i+=k<<1,w=mp(1,0))
for (int j=0;j<k;j++,w=w*wn)
x=a[i+j],y=w*a[i+j+k],a[i+j]=x+y,a[i+j+k]=x-y;
}
}
int main(){
freopen("program.in","r",stdin);
freopen("program.out","w",stdout);
scanf("%d",&n);n--;for (int i=1;i<=n;i++) g[i].fr=(DB)1/i/i;
for (int i=0;i<=n;i++) scanf("%lf",&f[i].fr),F[n-i]=f[i];
m=n;int len=0;for (n=1;n<=(m<<1);n<<=1) len++;for (int i=0;i<n;i++) R[i]=Rev(i,len);
FFT(f,n,1);FFT(F,n,1);FFT(g,n,1);for (int i=0;i<n;i++) f[i]=f[i]*g[i],F[i]=F[i]*g[i];
FFT(f,n,-1);FFT(F,n,-1);for (int i=0;i<=m;i++) printf("%.3f\n",(f[i].fr-F[m-i].fr)/n);
return 0;
}