正题
这题是我做过的最正经的FFT了。
其实
出题人很良心,已经帮你把它拆开了。
我们设
那么
前面的很明显是一个多项式乘法把,后面令,那么令
,然后多项式乘法就可以了。
这些限制可以丢掉,因为不满足的时候没有值,特殊的,我们只需要令
就可以了。
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn=3e6;
struct complex{
double x,y;
complex operator+(const complex a)const {return (complex){x+a.x,y+a.y};}
complex operator-(const complex a)const {return (complex){x-a.x,y-a.y};}
complex operator*(const complex a)const {return (complex){x*a.x-y*a.y,x*a.y+y*a.x};}
}q[maxn+10],Q[maxn+10],g[maxn+10];
int n,l,lim;
int where[maxn+10];
const double Pi=acos(-1.0)*2.0;
void dft(complex *now,int idft){
for(int i=0;i<lim;i++) if(where[i]>i) swap(now[i],now[where[i]]);
complex wn,w,a,b;
for(int l=2;l<=lim;l*=2){
wn=(complex){cos(Pi/l),idft*sin(Pi/l)};
for(int i=0;i<lim;i+=l){
w=(complex){1,0};
for(int x=i,y=i+l/2;y<i+l;x++,y++,w=w*wn){
a=now[x],b=now[y]*w;
now[x]=a+b;
now[y]=a-b;
}
}
}
}
int main(){
scanf("%d",&n);
for(int i=0;i<n;i++) scanf("%lf",&q[i].x),Q[n-1-i].x=q[i].x;
g[0].x=0;l=0;lim=1;
while(lim<2*n-1) lim*=2,l++;
for(int i=1;i<n;i++) g[i].x=1.0/i/i;
for(int i=0;i<lim;i++) where[i]=((where[i>>1]>>1)|((i&1)<<(l-1)));
dft(q,1);dft(g,1);dft(Q,1);
for(int i=0;i<lim;i++) q[i]=q[i]*g[i],Q[i]=Q[i]*g[i];
dft(q,-1);dft(Q,-1);
for(int i=0;i<n;i++) printf("%lf\n",q[i].x/lim-Q[n-1-i].x/lim);
}
本文深入探讨了快速傅立叶变换(FFT)算法在多项式乘法中的应用,通过实例讲解了如何利用FFT进行高效的计算,并提供了详细的代码实现,帮助读者理解FFT的工作原理及其在实际问题中的运用。
634

被折叠的 条评论
为什么被折叠?



