FFT(Fast Fourier Transform)
与其有关的有
DFT(Discrete Fourier Transform)
NTT(Number Theoretic Transforms)
类似的有
FWT(Fast Walsh-Hadamard Transform)
与FFT有关的应用
多项式乘法,卷积等等。
FFT算法讲解
一些你要知道的东东:
多项式相关
- 多项式:多个单项式相加得到的整式
- 多项式的次数界:其最高次项的次数加1,次数界为n的多项式最高次为
xn−1 - 多项式的表示方法为
A(x)=∑n−1i=0aixi - 多项式的点值运算:将多个不同值代入多项式的x,得出多个
(xi,A(xi)) 为该多项式的点值运算,一般用n的点(n为该多项式的次数界) - 多项式的差值运算:已知n个点得出过这些点次数界n的多项式
复数相关
- 虚数单位i:令
i=−1−−−√ ,满足i2=−1,i3=1i=−i,21−i=1+i 等诸多有趣性质 - 复数:形如
a+bi 的数成为复数,其中a为实部,b为虚部 - 复数直角坐标系:和平面直角坐标系类似,只是用x轴y轴表示实部虚部
- 复数的模长:
|z:a+bi|=a2+b2−−−−−−√ 即为该复数在复数直角坐标系中与原点的距离。 - 复数的辐角:复数直角坐标系中该复数与x轴的夹角
复数相乘,模长相乘,辐角相加(用和角公式可以证明)
令复数
z1:a+bi 辐角为θ1 ,z2:x+yi 辐角为θ2 ,z3=z1z2=ax−by+(ay+bx)i
设|z1|=l1,|z2|=l2,z′1=z1/l1,z′2=z2/l2 ,z′1:a′+b′i,z′2:x′+y′i
|z′1|=|z′2|=1∴a′=cos(θ1),b′=sin(θ1),x′=cos(θ2),y′=sin(θ2)
z3=z1z2=l1l2z′1z′2=l1l2(a′x′−b′y′+(a′y′+b′x′)i)=l1l2(cos(θ1)cos(θ2)−sin(θ1)sin(θ2)+(cos(θ1)sin(θ2)+sin(θ1)cos(θ2))i)
∴z3=l1l2(cos(θ1+θ2)+sin(θ1+θ2)i)
z′3:cos(θ1+θ2)+sin(θ1+θ2)i∴z3=l1l2z′3
易知|z′3|=1∴|z3|=|z1||z2| 方程
xn=1 的n次单位复数根为eiθ=cos(θ)+sin(θ)i (为什么,后面证)其中θ=2π/n ,第k个根为Wkn=eikπn ,令Wn=W1n -
Wkn=(Wn)k ,Wk+n2n=−Wkn ,Wan+kn=Wkn ,Wdkdn=Wkn (消去引理),(Wkn)2=W2kn=Wkn2 (折半引理)
——FFT干什么的?
——它是用来处理点值运算和插值运算的,这样它就可以实现多项式乘法了。
因为
点值运算
点值的取值呢?如果直接带入的话是
想到n次单位复数根与折半引理,是否可以利用分治呢?
下面给出算法:
易得
当
发现两条式子仅仅只是中间的加减号区别,所以只用枚举
流程大致如下:
void FFT(&A)
A0={a[0],a[2],a[4],...,a[n-2]}
A1={a[1],a[3],a[5],...,a[n-1]}
FFT(a0)FFT(a1)
for k(0->n/2-1)
A[k]=A0[k]+W[n/2][k]*A1[k]
A[k]=A0[k]-W[n/2][k]*A1[k]
差值运算
推式子可得
也就是将点值运算的
实现
如果每一次都递归一个数组的话,空间肯定会爆爆炸
观察它的转移方法:
发现x的排序方式是按照二进制反串的大小排的
给出一个高级式子:
for(int i=0,p=0;i<n;i++){
if(i<p)swap(x[i],x[p]);
for(int j=n>>1;(p^=j)<j;j>>=1);
}
然后再枚举哪一个位置哪一块转移即可。
void dft(z *a,db sig){
for(int i=0;i<n;++i)y[i]=a[i];
for(int i=0,p=0;i<n;i++){
if(i<p)swap(y[i],y[p]);
for(int j=n>>1;(p^=j)<j;j>>=1);
}
for(int m=2;m<=n;m<<=1){
int hf=m>>1;
for(int i=0;i<hf;i++){
db aug=(db)i/(db)hf*M_PI*sig;
z w=(z){cos(aug),sin(aug)};
for(int j=i;j<=n;j+=m){
int k=j+hf;
z u=y[j],v=y[k]*w;
y[j]=u+v;y[k]=u-v;
}
}
}
for(int i=0;i<n;i++)a[i]=y[i];
}
呃呃插一句对
这是个不严谨的严谨证明,最严谨的严谨证明要用到泰勒公式,我不会。。。