1.FFT(快速傅里叶变换)
1.前置技能
复数:
基本表示法及性质:
i = − 1 i=\sqrt{-1} i=−1
i i i是虚数单位
1.坐标(代数)形式:
z = a + b i z=a+bi z=a+bi
当b为0是z为实数,当a为0时为纯虚数
注:复数包括实数和虚数,虚数下有纯虚数
虚数z对应了复平面上的一点(a,b)
运算法则:
设复数 z 1 , z 2 , z 1 = a + b i , z 2 = c + d i z_1,z_2,z_1=a+bi,z_2=c+di z1,z2,z1=a+bi,z2=c+di
加法: z 1 + z 2 = ( a + c ) + ( b + d ) i z_1+z_2=(a+c)+(b+d)i z1+z2=(a+c)+(b+d)i
减法: z 1 − z 2 = ( a − c ) + ( b − d ) i z_1-z_2=(a-c)+(b-d)i z1−z2=(a−c)+(b−d)i
乘法: z 1 ∗ z 2 = ( a c − b d ) + ( b c + a d ) i z_1*z_2=(ac-bd)+(bc+ad)i z1∗z2=(ac−bd)+(bc+ad)i
除法: z 1 z 2 = ( a c + b d ) + ( b c − a d ) i ( c 2 + d 2 ) \dfrac{z_1}{z_2}=\dfrac{(ac+bd)+(bc-ad)i}{(c^2+d^2)} z2z1=(c2+d2)(ac+bd)+(bc−ad)i
2.三角形式
z = r ( c o s θ + i s i n θ ) z=r(cos \theta+isin\theta) z=r(cosθ+isinθ)
θ \theta θ是复数 z z z的幅角, r r r是该复数的模长
这种形式下的乘法和除法运算更方便,通过和角公式,对于复数 z 1 = r 1 ( c o s θ 1 + i s i n θ 1 ) , z 2 = r 2 ( c o s θ 2 + i s i n θ 2 ) z_1=r_1(cos\theta_1+isin\theta_1),z_2=r_2(cos\theta_2+isin\theta_2) z1=r1(cosθ1+isinθ1),z2=r2(cosθ2+isinθ2)
那么:
z 1 z 2 = r 1 r 2 ( c o s ( θ 1 + θ 2 ) + i s i n ( θ 1 + θ 2 ) ) z 1 z 2 = r 1 r 2 ( c o s ( θ 1 − θ 2 ) + i s i n ( θ 1 − θ 2 ) ) z_1z_2=r_1r_2(cos(\theta_1+\theta_2)+isin(\theta_1+\theta_2))\\ \dfrac{z_1}{z_2}=\dfrac{r_1}{r_2}(cos(\theta_1-\theta_2)+isin(\theta_1-\theta_2))\\ z1z2=r1r2(cos(θ1+θ2)+isin(θ1+θ2))z2z1=r2r1(cos(θ1−θ2)+isin(θ1−θ2))
几何意义:相当于把该复数 拉长/缩短 到另一个复数模长 倍/分之一 ,然后 顺时针/逆时针 旋转另一个复数的幅角大小的角度
于是有了如下非常有用的公式:
z n = ( r ( c o s θ + i s i n θ ) ) n = r n ( c o s n θ + i s i n n θ ) z^n=(r(cos\theta+isin\theta))^n=r^n(cos\ n\theta+isin\ n\theta) zn=(r(cosθ+isinθ))n=rn(cos nθ+isin nθ)
3.指数形式
z = r e i θ z=re^{i\theta} z=reiθ
于是我们知道了: e i θ = c o s θ + i s i n θ e^{i\theta}=cos\theta+isin\theta eiθ=cosθ+isinθ
可以发现: e i π = − 1 e^{i\pi}=-1 eiπ=−1
(优美)
这个算乘除法就更好算了:
有:
z 1 z 2 = r 1 r 2 e i ( θ 1 + θ 2 ) z 1 z 2 = r 1 r 2 e i ( θ ) z_1z_2=r_1r_2e^{i(\theta_1+\theta_2)}\\ \dfrac{z_1}{z_2}=\dfrac{r_1}{r_2}e^{i(\theta)}\\ z1z2=r1r2ei(θ1+θ2)z2z1=r2r1ei(θ)
上面的那个公式就可写成这样:
z n = r n e i ( n θ ) z^n=r^ne^{i(n\theta)} zn=rnei(nθ)
4.单位复数根
学FFT最重要的就这个了吧
设有如下方程:
z n = 1 z^n=1 zn=1
这方程的复数根 z z z为 n n n次单位根,通常记为 w w w
这样的根 w w w有n个,也就是说 n n n次单位根有 n n n个,记为 w k ( k = 0 , 1 , 2 , … n − 1 ) w_k (k=0,1,2,\dots n-1) wk(k=0,1,2,…n−1)
其中:
w k = c o s 2 k π n + i s i n 2 k π n = e 2 π k i n w_k=cos\frac{2k\pi}{n}+isin\frac{2k\pi}{n}=e^{\frac{2\pi ki}{n}} wk=cosn2kπ+isinn2kπ=en2πki
不难发现其实 n n n次单位复数根就是把复平面上的单位圆 n n n 等分后的那些 n n n等分点
一些次数单位的单位根举例:
1次单位根: 1 1 1
2次单位根: 1 , − 1 1,-1 1,−1
3次单位根: 1 , − 1 + 3 i 2 , − 1 − 3 i 2 1,\frac{-1+\sqrt{3}i}{2},\frac{-1-\sqrt{3}i}{2} 1,2−1+3i,2−1−3i
… \dots …
其实就是个解二元n次方程
可以发现1是任意次的单位复数根,-1是任意偶数次单位复数根
某些引理:
1.消去引理
w d n d k = w n k w_{dn}^{dk}=w_n^k wdndk=wnk
把复数的指数形式带进去就可以了
说人话就是不同次数的单位根可以互相转化
2.折半引理
假设 n n n是大于0的偶数:
( w n k + n 2 ) 2 = w n 2 k + n = w n 2 k ∗ w n n = ( w n k ) 2 (w_n^{k+\frac{n}{2}})^2=w_n^{2k+n}=w_n^{2k}*w_n^n=(w_n^{k})^2 (wnk+2n)2=wn2k+n=wn2k∗wnn=(wnk)2
说人话就是n次单位复数根的前后两半平方后是对应相等的
3.求和引理
对于大于1的整数n和小于等于n的整数k有:
∑ i = 0 n − 1 ( w n k ) i = 0 \sum_{i=0}^{n-1}(w_n^k)^i=0 i=0∑n−1(wnk)i=0
这就是个等比数列求和
2.步入正题
常规的一个最高次数为n-1的多项式的表示形式是系数表示法,如:
A ( x ) = a 0 + a 1 x + a 2 x 2 + a 3 x 3 + ⋯ + a n − 1 x n − 1 A(x)=a_0+a_1x+a_2x^2+a_3x^3+\dots+a_{n-1}x^{n-1} A(x)=a0+a1x+a2x2+a3x3+⋯+an−1xn−1
一共有n项
按照朴素的多项式乘法(卷积),就是每一项两两相乘,复杂度为 O ( n 2 ) O(n^2) O(n2)
如果我们把多项式看成一个函数,我们取图像上的n个点来表示这个函数也即该多项式,这样的表示法叫做点值表示法
对于两个n-1次多项式,由于我们最后卷积出来的多项式是2n-2次的,如果我们知道了卷积后的多项式函数图像上的至少2n-1个点,那么我们就可以确定这个多项式了
所以有如下想法:
现在原来的两个多项式上选取好x值相同的点(个数为原来两多项式次数的和加1),用 O ( n ) O(n) O(n)的时间将选的点的y值相乘,得到的值用某种方法~~(待定系数法)~~转化为多项式系数的形式
如果选取的x都是n次单位复数根的k次方,那么以上两个过程就是 D F T DFT DFT和 I D F T IDFT IDFT了
1. D F T DFT DFT
离散傅里叶变换:
对于 k ∈ [ 0 , n − 1 ] , k\in [0,n-1], k∈[0,n−1],和n-1次多项式 A ( x ) , A(x), A(x),定义:
y k = A ( w n k ) = ∑ i = 0 n − 1 a i ( w n k ) i y_k=A(w_n^k)=\sum_{i=0}^{n-1}a_i(w_n^k)^i yk=A(wnk)=i=0∑n−1ai(wnk)i
这个叫做离散傅里叶变换,记做 y = D F T n ( a ) y=DFT_n(a) y=DFTn(a)
朴素求 D F T DFT DFT,是 O ( n 2 ) O(n^2) O(n2)的
2. I D F T IDFT IDFT
逆离散傅里叶变换:
就是 D F T DFT DFT的逆运算,用于求出多项式的系数a,记为 D F T − 1 DFT^{-1} DFT−1
本人太弱不会证,丢个式子:
a k = 1 n ∑ i = 0 n − 1 y i ( w n − k ) i a_k=\dfrac{1}{n}\sum_{i=0}^{n-1}y_i(w_n^{-k})^i ak=n1i=0∑n−1yi(wn−k)i
由于写的时候系数表达式和点值表达式是共用的数组,所以写起来和 D F T DFT DFT没什么差别
3. F F T FFT FFT
快速傅里叶变换:
是一种快速求出 D F T DFT DFT和 D F T − 1 DFT^{-1} DFT−1的算法,利用了单位复数根的优良性质
我们先列出朴素求 D F T DFT DFT的步骤,为了方便这里先不妨假设多项式次数为2的幂:
1.求出n次单位复数根的幂: w n 0 , w n 1 , w n 2 . . . . . w n n − 1 w_n^0,w_n^1,w_n^2.....w_n^{n-1} wn0,wn1,wn2.....wnn−1
2.代入多项式 A ( x ) A(x) A(x),求得以下式子:
A ( w n 0 ) = a 0 + a 1 w n 0 + a 2 ( w n 0 ) 2 + a 3 ( w n 0 ) 3 + … a n − 1 ( w n 0 ) n − 1 A ( w n 1 ) = a 0 + a 1 w n 1 + a 2 ( w n 1 ) 2 + a 3 ( w n 1 ) 3 + … a n − 1 ( w n 1 ) n − 1 A ( w n 2 ) = a 0 + a 1 w n 2 + a 2 ( w n 2 ) 2 + a 3 ( w n 2 ) 3 + … a n − 1 ( w n 2 ) n − 1 A ( w n 3 ) = a 0 + a 1 w n 3 + a 2 ( w n 3 ) 2 + a 3 ( w n 3 ) 3 + … a n − 1 ( w n 3 ) n − 1 … … … … … … … … … … … … … … … … … A ( w n n − 1 ) = a 0 + a 1 w n n − 1 + a 2 ( w n n − 1 ) 2 + a 3 ( w n n − 1 ) 3 + … a n − 1 ( w n n − 1 ) n − 1 A(w_n^0)=a_0+a_1w_n^0+a_2(w_n^0)^2+a_3(w_n^0)^3+\dots a_{n-1}(w_n^0)^{n-1}\\ A(w_n^1)=a_0+a_1w_n^1+a_2(w_n^1)^2+a_3(w_n^1)^3+\dots a_{n-1}(w_n^1)^{n-1}\\ A(w_n^2)=a_0+a_1w_n^2+a_2(w_n^2)^2+a_3(w_n^2)^3+\dots a_{n-1}(w_n^2)^{n-1}\\ A(w_n^3)=a_0+a_1w_n^3+a_2(w_n^3)^2+a_3(w_n^3)^3+\dots a_{n-1}(w_n^3)^{n-1}\\ \dots\dots\dots\dots\dots\dots\dots\dots\dots\dots\dots\dots\dots\dots\dots\dots\dots\\ A(w_n^{n-1})=a_0+a_1w_n^{n-1}+a_2(w_n^{n-1})^2+a_3(w_n^{n-1})^3+\dots a_{n-1}(w_n^{n-1})^{n-1}\\ A(wn0)=a0+a1wn0+a2(wn0)2+a3(wn0)3+…an−1(wn0)n−1A(wn1)=a0+a1wn1+a2(wn1)2+a3(wn1)3+…an−1(wn1)n−1A(wn2)=a0+a1wn2+a2(wn2)2+a3(wn2)3+…an−1(wn2)n−1A(wn3)=a0+a1wn3+a2(wn3)2+a3(wn3)3+…an−1(wn3)n−1……………………………………………A(wnn−1)=a0+a1wnn−1+a2(wnn−1)2