自从机房掀起学习数学之风,我便跟风学起了数学(其实是因为不会)
众所周知FFT很有用(一开始真是不太好理解)。
首先上大佬的博客:
1.胡小兔(对不起我不如小学生)
2.路人黑的纸巾
3.GGN_2015
4.自为风月马前卒
接下来是正文(我抄的)。
FFT(Fast Fourier Transformation),中文名快速傅里叶变换,用来加速多项式乘法
前置知识:无吧?(反正我上数学课顺便看了看复数的基础知识就过来学了)
啊好吧还是有的
向量
同时具有大小和方向的量
在几何中通常用带有箭头的线段表示
圆的弧度制
等于半径长的圆弧所对的圆心角叫做1弧度的角,用符号rad表示,读作弧度。用弧度作单位来度量角的制度叫做弧度制
公式:
1∘=π180rad1∘=π180rad
180∘=πrad180∘=πrad
平行四边形定则
平行四边形定则:AB+AD=AC
系数表示法
设A(x)表示一个n−1次多项式
则A(x)=∑ni=0ai∗xi
例如:A(3)=2+3∗x+x2
利用这种方法计算多项式乘法复杂度为O(n2)
(第一个多项式中每个系数都需要与第二个多项式的每个系数相乘)
点值表示法
将nn互不相同的xx带入多项式,会得到nn个不同的取值yy
则该多项式被这nn个点(x1,y1),(x2,y2),…,(xn,yn))唯一确定
其中yi=∑n−1j=0aj∗xji
例如:上面的例子用点值表示法可以为(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;
运算:直接使用加减乘除。
代数定义:
傅里叶要用到的n个复数,不是随机找的,而是——把单位圆(圆心为原点、1为半径的圆)n等分,取这n个点(或点表示的向量)所表示的虚数,即分别以这n个点的横坐标为实部、纵坐标为虚部,所构成的虚数。
从点(1,0)(1,0)开始(显然这个点是我们要取的点之一),逆时针将这n个点从0开始编号,第kk个点对应的虚数记作ωnk(根据复数相乘时模长相乘幅角相加可以看出,ωnk是w1n的k次方,所以ω1n被称为n次单位根)。
单位根的性质
为什么要使用单位根作为xx代入
答:因为离散傅里叶变换有着特殊的性质。
一个结论
把多项式A(x)A(x)的离散傅里叶变换结果作为另一个多项式B(x)B(x)的系数,取单位根的倒数即ω0n,ω−1n,ω−2n,...,ω−(n−1)nωn0,ωn−1,ωn−2,...,ωn−(n−1)作为xx代入B(x)B(x),得到的每个数再除以n,得到的是A(x)A(x)的各项系数
正主出场
快速傅里叶变换
快速傅里叶变换的数学证明
仍然,我们设A(x)=a0+a1x+a2x2+...+an−1xn−1A(x)=a0+a1x+a2x2+...+an−1xn−1,现在为了求离散傅里叶变换,要把一个x=ωknx=ωnk代入。
考虑将A(x)A(x)的每一项按照下标的奇偶分成两部分:
设两个多项式:
则:
假设k<n2k<n2,现在要把x=ωknx=ωnk代入:
那么对于A(ωk+n2n)A(ωnk+n2):
所以,如果我们知道两个多项式A1(x)A1(x)和A2(x)A2(x)分别在(ω0n2,ω1n2,ω2n2,...,ωn2−1n2(ωn20,ωn21,ωn22,...,ωn2n2−1)的点值表示,就可以O(n)O(n)求出A(x)A(x)在ω0n,ω1n,ω2n,...,ωn−1nωn0,ωn1,ωn2,...,ωnn−1处的点值表示了。而A1(x)A1(x)和A2(x)A2(x)都是规模缩小了一半的子问题。分治边界是n=1n=1,此时直接return。