1. 程式人生 > >FFT演算法講解——麻麻我終於會FFT了!

FFT演算法講解——麻麻我終於會FFT了!

FFT——快速傅立葉變換

這塊不寫東西空蕩蕩的,我決定還是把FFT的定義給貼上吧

FFT(Fast Fourier Transformation)是離散傅氏變換(DFT)的快速演算法。即為快速傅氏變換。它是根據離散傅氏變換的奇、偶、虛、實等特性,對離散傅立葉變換的演算法進行改進獲得的。

這三段話其實一點用也沒有

FFT是幹什麼的

FFT在演算法競賽中就有一個用途:加速多項式乘法(暴言)

簡單來說,形如 a0X0+a1X1+a2X2++anXna_0X^0+a_1X^1+a_2X^2+⋯+a_nX^n 的代數表示式叫做多項式,可以記作f(X)=a0X0+a

1X1+a2X2++anXnf(X)=a_0X^0+a_1X^1+a_2X^2+⋯+a_nX^n,其中a0,a1,,ana_0,a_1,⋯,a_n叫做多項式的係數XX是一個不定元(就是不可以合併),不表示任何值,不定元在多項式中最大項的次數稱作多項式的次數

如果我們當前有兩個多項式f(X),g(X)f(X),g(X),現在要把他們乘起來(求卷積),最樸素的做法就是

i=02n1(j=0iajbij)xi\sum \limits _{i=0}^{2n-1} (\sum \limits _{j=0} ^{i} a_j*b_{i-j})*x^i

這樣的複雜度是Θ(n2)\varTheta(n^2)的,十分不美觀,FFT就是要將這個過程優化為Θ(nlogn)\varTheta(n \log n)

前置技能

多項式

見上文

複數

複數形如a+bia+bi,其中i=1i=\sqrt {-1}

aa叫作複數的實部,bibi叫做複數的虛部

複數(a1+b1i)(a2+b2i)(a_1+b_1i)*(a_2+b_2i)相乘的值,即a1a2b1b2+(a1b2+a2b1)ia_1a_2-b_1b_2+(a_1b_2+a_2b_1)i

也是一個複數,同時我們也得到了複數的乘法法則

複數c+dic+di可以用這種方式表示出來

(c+di)

複數乘法的在複平面中表現為輻角相加,模長相乘

單位根

複數ww滿足wn=1w^n=1稱作wwnn次單位根,下圖包含了所有的88次單位根(圖中圓的半徑是1)

8次單位根

同樣的,下圖是所有的4次單位根

4次單位根

聰明的你也許已經發現了單位根的些許性質,即

w2n2m=wnmw_{2n}^{2m}=w_{n}^{m}

wnm=wnm+n2w_n^m=-w_n^{m+\frac{n}{2}}

這兩個要記住,一會很有用

多項式的係數表達法

我們有多項式f(X)=a0X0+a1X1+a2X2++anXnf(X)=a_0X^0+a_1X^1+a_2X^2+⋯+a_nX^n,令a=(a0,a1,a2,...,an)\vec{a}=(a_0,a_1,a_2,...,a_n),則稱A(X)A(X)為多項式f(X)f(X)的係數表示法

在係數表示法下,計算多項式乘法是Θ(n2)\varTheta (n^2)

多項式的點值表達法

任取n+1n+1互不相同S={p1,p2,...,pn+1}S=\{p_1,p_2,...,p_{n+1}\},對f(X)f(X)分別求值得到f(p1),f(p2),...,f(pn+1)f(p_1),f(p_2),...,f(p_{n+1}),那麼稱A(X)={(p1,f(p1)),(p2,f(p2)),...,(pn+1,f(pn+1))}A(X)=\{(p_1,f(p_1)),(p_2,f(p_2)),...,(p_{n+1},f(p_{n+1}))\}為多項式f(X)f(X)SS下的點值表示法

可以把多項式想象成一個nn次函式,點值表示法就是取SS下每一個橫座標時對應的點,因為nn次函式可以由n+1n+1個點確定下來(可以將每一個點列一個nn次方程),所以nn維點值與nn維繫數一一對應

更重要的一點,點值表示法下的乘法運算獲得了簡化

兩個多項式PP,QQ分別取點(x,y1)(x,y_1)(x,y2)(x,y_2)PQP*Q就會取到點(x,y1y2)(x,y_1*y_2)

C=PQC=P*Q,因為C(X)=P(X)Q(X)C(X)=P(X)*Q(X),所以C(x)=P(