终于学这个了!
不瞒你说,第一次见到这个是某场比赛有个队伍的队名是"我的表弟不会快速傅里叶变换", 这个队伍好像还蛮强的耶.....
第二次见到这个东西是在某次开题的时候,我还记得有个题目叫做 3 idiots (三个滞涨), 后来戏称我们队伍是滞涨组合, 原因是那次开的比赛我们三个滞涨全部把各自的题目看错了......
啊跑题了, 反正那道题我们一开始用最朴素的方法去解,当然是超时的啦, 怎么优化复杂度都是n^2, 然后队长同志悄咪咪地去搜了一下题解发现用的是快速傅里叶变换, 那没学过自然就放弃咯, 现在终于学到这个东西了.
关于这个模板如何使用, 这个需要很大的篇幅用以描述, 我会另写一篇题目来表示这个东西怎么用.
模板如下:
const double PI=acos(-1);//这个是一定要有的, 因为fft有应用到三角函数,因此头文件math.h也要包含进去
struct complex
{
double a,b;//a表示实部,b表示虚部
complex(double aa=0.0,double bb=0.0)
{
a=aa;
b=bb;
}
complex operator +(const complex &e)
{//重载运算符+用以直接进行虚数相加,下同
return complex(a+e.a,b+e.b);
}
complex operator -(const complex &e)
{//重载运算符-
return complex(a-e.a,b-e.b);
}
complex operator *(const complex &e)
{//重载运算符*
return complex(a*e.a-b*e.b,a*e.b+b*e.a);
}
};
void change(complex *y,int len)
{//change这个词还挺常用于给自己写的功能函数重名的,要注意一下,不过有可能以后更新模板就换掉了
int i,j,k;
for(i=1,j=len/2;i<len-1; i++)
{
if(i<j)
swap(y[i],y[j]);
k=len/2;
while(j>=k)
{
j-=k;
k>>=1;
}
if(j<k)
{
j+=k;
}
}
}
void fft(complex *y,int len,int on)
{
change(y, len);
int i,j,k;
for(i=2;i<=len;i<<=1)
{
complex wn(cos(-on*2*PI/i),sin(-on*2*PI/i));
for(j=0;j<len;j+=i)
{
complex w(1,0);
for(k=j;k<j+i/2;k++)
{
complex u=y[k],t=w*y[k+i/2];
y[k]=u+t;
y[k+i/2]=u-t;
w=w*wn;
}
}
}
if(on==-1)//还原回原来的多项式
for(i=0;i<len;i++)
y[i].a/=len;
}