前言:
下了好大決心,花了一個晚上的時間,終於看懂了FFT的理論與流程,然後又花了一個晚上實現代碼,做了幾道模板題。
FFT理論很深,卻又很實用,一個很常用的用法就是加速多項式乘法,使得原來O(n^2)的複雜度減小到O(nlogn)。
下面我來大概講述一下FFT的基本理論與算法流程,幫助初學者瞭解FFT,同時也是自己的複習。
<1> 介紹:
FFT,全稱快速傅里葉變換(fast Fourier transform),是用來計算離散傅里葉變換(DFT)及其逆變換(IDFT)的快速算法。對於DFT,迷一點講就是說它把時域信號轉化爲頻域信號(不明白也沒關係,並不影響學習算法)。在算法競賽中,我們經常用FFT來加速卷積,做一些多項式乘法或是高精度乘法之類的。
我主要基於多項式乘法來介紹FFT,下面也都是用多項式乘法來講的~
<2>一些定義:
我們將一個以x爲變量的多項式A(x)表示爲:
若多項式
若有兩個以x爲變量的n次多項式
其中
另外,下面還大量提到了複數,並用專用符號
<3>係數表達與點值表達:
對一個次數界爲n的多項式
而它的點值表達是一個由n個點值對組成的集合
使得對
對於點值表達,我們可以看成是把多項式
我們可以看到,求出這個多項式的n個點值複雜度爲
我們將求值運算的逆稱爲插值(就是通過點值表達來求出係數表達),有一個定理(差值多項式的唯一性):對於任意n個點值對組成的集合,其中所有的
對於多項式乘法,點值表達是十分方便的。若
若
<4>FFT的大致流程:
現在我們已經能在線性時間內將兩個多項式進行乘法操作了,那麼剩下的問題就是如何快速實現多項式係數表達與點值表達的快速轉化。
上面提到如果巧妙地選取
現在給出FFT算法的大致流程:
*1.加倍次數界:將兩個多項式
*2.求值:將係數表達式轉化爲點值表達式(用2n階的FFT(DFT),求出多項式在2n次單位復根處的值)。
*3.逐點相乘:將兩個多項式點值表達中的
*4.差值:利用積的點值表達再用FFT(IDFT)求出係數表達。
如此,多項式乘法就做完了,我們從兩個多項式的係數表達,得到了積的係數表達。
<5>單位複數根:
學FFT,這是極其重要的一點,希望能完全理解其中的變換與結論,最好能手動推算一下,並不難推,大部分是基礎的指數運算,但推過與沒推過是有很大區別的。
n次單位復根是滿足
複數的指數形式的定義:
並且值
稱爲主n次單位根,所有其它n次單位復根都是
可以得到
消去引理:對任何整數 n>=0,k>=0,以及d>0,
推論:對任意偶數,有
折半引理:如果n>0爲偶數,那麼n個n次單位複數根的平方的集合就是n/2個n/2次單位複數根的集合。
證明:
根據消去引理,有
求和引理:對任意整數n>=1和不能被n整除的非負整數k,有
注:用等差數列的求和公式推導即可。
<6>DFT:
我們希望計算次數界爲n的多項式
我們也記
<7>FFT:
通過FFT,利用單位複數根的特殊性質,我們就可以在
FFT採用分治,將原多項式偶數下標與奇數下標的係數分開,得到兩個新的n/2次多項式
其中,
於是有:
於是,就可以遞歸分治處理了。
下面給出FFT的僞代碼:
}
注意:
<8>插值:
現在我們已經知道了如何快速的通過係數表達,在單位復根處快速求出點值,那麼,接下來就只剩下最後一項任務,那就是在快速時間內完成DFT的逆過程IDFT,在單位復根處插值,得到結果的係數表達。
我們可以把DFT寫成矩陣乘積
定理:
至於證明,只需把矩陣乘法各點的式子寫出來,結合求和引理,就可以發現
於是可以推出
其中
我們比較第6節中的式子,發現只要做出以下修改:
*1:把a與y互換
*2:用
*3:將計算結果每個除以n
最後再來一個定理
卷積定理:對任意兩個長度爲n的向量a和b,其中n是2的冪,
最後,感謝大家的閱讀!
如有不足之處,儘可在評論中指出。
本文參考文獻:
《算法競賽入門經典訓練指南》——劉汝佳
《算法導論》
(注:本文大部分內容均摘自算法導論,自己加以篩選、註釋,第7節中提到的推導過程書中有介紹,若沒想出來可以查閱(P534))
轉載自:http://blog.csdn.net/Monkey_king2017cn/article/details/77542160