毒瘤的FFT笔记

落爺英雄遲暮 提交于 2019-12-01 20:11:29

自从机房掀起学习数学之风,我便跟风学起了数学(其实是因为不会)

众所周知FFT很有用(一开始真是不太好理解)。

首先上大佬的博客:

1.胡小兔(对不起我不如小学生)

2.路人黑的纸巾

3.GGN_2015

4.自为风月马前卒

接下来是正文(我抄的)。

FFT(Fast Fourier Transformation),中文名快速傅里叶变换,用来加速多项式乘法

前置知识:无吧?(反正我上数学课顺便看了看复数的基础知识就过来学了)

啊好吧还是有的

向量

同时具有大小和方向的量

在几何中通常用带有箭头的线段表示

圆的弧度制

等于半径长的圆弧所对的圆心角叫做1弧度的角,用符号rad表示,读作弧度。用弧度作单位来度量角的制度叫做弧度制

公式:

1=π180rad1∘=π180rad

180=πrad180∘=πrad

平行四边形定则

 

平行四边形定则:AB+AD=AC

系数表示法

A(x)表示一个n1次多项式

A(x)=ni=0aixi

例如:A(3)=2+3x+x2

利用这种方法计算多项式乘法复杂度为O(n2)

(第一个多项式中每个系数都需要与第二个多项式的每个系数相乘)

点值表示法

nn互不相同的xx带入多项式,会得到nn个不同的取值yy

则该多项式被这nn个点(x1,y1),(x2,y2),,(xn,yn))唯一确定

其中yi=n1j=0ajxji

例如:上面的例子用点值表示法可以为(0,2),(1,6),(2,12)

利用这种方法计算多项式乘法的时间复杂度仍然为O(n^2)

(选点O(n),每次计算O(n)

复数

定义

a,ba,b为实数,i2=1i2=−1,形如a+bia+bi的数叫复数,其中ii被称为虚数单位,复数域是目前已知最大的域

在复平面中,xx代表实数,yy轴(除原点外的点)代表虚数,从原点(0,0)(0,0)到(a,b)(a,b)的向量表示复数a+bia+bi

模长:从原点(0,0)(0,0)到点(a,b)(a,b)的距离,即a2+b2−−−−−−√a2+b2

幅角:假设以逆时针为正方向,从xx轴正半轴到已知向量的转角的有向角叫做幅角

C++的STL提供了复数模板!
头文件:#include <complex>
定义: complex<double> x;
运算:直接使用加减乘除。

代数定义:

(a+bi)(c+di)(a+bi)∗(c+di)
=ac+adi+bci+bdi2=ac+adi+bci+bdi2
=ac+adi+bcibd=ac+adi+bci−bd
=(acbd)+(bc+ad)i

傅里叶要用到的n个复数,不是随机找的,而是——把单位圆(圆心为原点、1为半径的圆)n等分,取这n个点(或点表示的向量)所表示的虚数,即分别以这n个点的横坐标为实部、纵坐标为虚部,所构成的虚数。

从点(1,0)(1,0)开始(显然这个点是我们要取的点之一),逆时针将这n个点从0开始编号,第kk个点对应的虚数记作ωnk(根据复数相乘时模长相乘幅角相加可以看出,ωnk是w1nk次方,所以ω1n被称为n次单位根)。

单位根的性质

为什么要使用单位根作为xx代入

答:因为离散傅里叶变换有着特殊的性质。

一个结论

把多项式A(x)A(x)的离散傅里叶变换结果作为另一个多项式B(x)B(x)的系数,取单位根的倒数即ω0n,ω1n,ω2n,...,ω(n1)nωn0,ωn−1,ωn−2,...,ωn−(n−1)作为xx代入B(x)B(x),得到的每个数再除以n,得到的是A(x)A(x)的各项系数

 

正主出场

快速傅里叶变换

快速傅里叶变换的数学证明

仍然,我们设A(x)=a0+a1x+a2x2+...+an1xn1A(x)=a0+a1x+a2x2+...+an−1xn−1,现在为了求离散傅里叶变换,要把一个x=ωknx=ωnk代入。

考虑将A(x)A(x)的每一项按照下标的奇偶分成两部分:

 

A(x)=(a0+a2x2+...+an2xn2)+(a1x+a3x3+...+an1xn1)A(x)=(a0+a2x2+...+an−2xn−2)+(a1x+a3x3+...+an−1xn−1)

 

设两个多项式:

 

A1(x)=a0+a2x+...+an2xn21A1(x)=a0+a2x+...+an−2xn2−1

 

A2(x)=a1+a3x+...+an1xn21A2(x)=a1+a3x+...+an−1xn2−1

 

则:

 

A(x)=A1(x2)+xA2(x2)A(x)=A1(x2)+xA2(x2)

 

假设k<n2k<n2,现在要把x=ωknx=ωnk代入:

 

A(ωkn)=A1(ω2kn)+ωknA2(ω2kn)=A1(ωkn2)+ωknA2(ωkn2)A(ωnk)=A1(ωn2k)+ωnkA2(ωn2k)=A1(ωn2k)+ωnkA2(ωn2k)

 

那么对于A(ωk+n2n)A(ωnk+n2):

 

A(ωk+n2n)=A1(ω2k+nn)+ωk+n2nA2(ω2k+nn)=A1(ωkn2×ωnn)+ωk+n2nA2(ωkn2×ωnn)=A1(ωkn2)ωknA2(ωkn2)A(ωnk+n2)=A1(ωn2k+n)+ωnk+n2A2(ωn2k+n)=A1(ωn2k×ωnn)+ωnk+n2A2(ωn2k×ωnn)=A1(ωn2k)−ωnkA2(ωn2k)

 

所以,如果我们知道两个多项式A1(x)A1(x)和A2(x)A2(x)分别在(ω0n2,ω1n2,ω2n2,...,ωn21n2(ωn20,ωn21,ωn22,...,ωn2n2−1)的点值表示,就可以O(n)O(n)求出A(x)A(x)在ω0n,ω1n,ω2n,...,ωn1nωn0,ωn1,ωn2,...,ωnn−1处的点值表示了。而A1(x)A1(x)和A2(x)A2(x)都是规模缩小了一半的子问题。分治边界是n=1n=1,此时直接return。

 

 

 

 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!