1.了解函式,多項式等概念
2.了解複數以及其乘法運算
3.會寫**(其實不會的人也不會來看這篇文章?)
因為在看其他fft的教程的時候複數讀完就不知道在說啥了,讀了好多篇又抄了std才大致了解,所以通俗的講一下fft是啥,主要是確定一下概念,梳理一下思路。一些更基礎的內容就不再贅述了,如果遇到不知道複數是什麼之類的,那可以看一下其他的教程。
法法塔(fft)全稱快速傅利葉變換(fast fourier transform),我們經常在求高精度乘法的時候用到這個演算法,但是高精乘只是本身fft的一種應用,事實上,傅利葉變換本身只是一種將多項式在點值表示法和多項式表示法之間轉換的方法。
我們考慮乙個n次多項式p(x)和另乙個m次多項式q(x),當我們將x取為10,那麼事實上多項式就表示乙個十進位制數。我們在做乘法的時候,可以將p(x)和q(x)做卷積,也就是我們日常所用的豎式乘法,得到乙個新的多項式a(x)=p(x) * q(x)。對a(x)取x=10,就可以得到乘法的結果。這樣做的複雜度是o(m * n)。
我們上面是在多項式表示法下解決多項式乘法問題,事實上我們還有另一種解決方案。
我們先介紹多項式的點值表示法。對於乙個n次多項式p(x),如果我們能在平面上取n+1個點,記為h(x)=,那麼我們一定可以定出乙個唯一的n次多項式(當然,也可以取更多的點,只要這些點都落在多項式函式上就可以,它等價於乙個大於n的次數的係數都為0的更高次多項式,事實上我們在後面操作時的確會取過量個點)。此時我們可以稱h(x)和p(x)等價。
那麼假設我們現在有兩個點值表示法下的多項式h(x),g(x),我們不妨取n=(h的次數+y的次數+1)個點,這樣我們一定可以正確表示兩個小於等於n次的多項式h(x)和g(x)。那麼接下來我們可以很快速的求解對應的點值表示法下的多項式:考慮每乙個選取的橫座標x,我們有y1=h(x),y2=g(x),當這這兩個多項式的乘積也y3=z(x)一定滿足:
y3 = y1 * y2
這個很容易理解,想象一下,當x=10時,這不就是我們熟知的乘法嗎?只不過是直接在結果上的表現形式罷了。
而因為我們取得點足夠多,所以求出來的n個點一定足夠表述z(x)這個多項式方程。
這樣,我們就可以在o(n+m)時間[兩個多項式的長度分別為n,m的情況下]內求解多項式乘法,也就是將這麼多個點對應相乘即可。
那麼現在我們要解決的問題就是:如何將點值表示法和多項式表示法進行快速的轉換。
怎麼樣把多項式表示法變成點值表示法呢,乙個簡單的想法是,隨便取一些點,求出對應的值,那麼就完成了。那麼怎麼變回去呢?這就是離散傅利葉變換給我們提供的思路:如果我們在將多項式變成點值表示法時取一些特殊的點,那麼我們就可以用類似的方法將點值表示法變回多項式表示法。
傅利葉告訴我們,如果我們要取n個點,那麼取n次單位復根就會有乙個美妙的性質。(如果你是從其他教程過來的,那麼應該知道這說的是啥,就不多做贅述了。)
接下來講一下為什麼要取這些值呢?
這一篇裡面的數學推導非常直白我這裡就直接用他的圖了。
這是什麼意思呢?
意思就是,如果我們取單位負根,那麼我們就能用幾乎一模一樣的函式把點值表示法變回多項式表示法,這是x取單位復根的意義。事實上,這個單位負根和我們求出來的結果其實沒什麼關係,這個單純是用來做變換的手段。
但是,直接帶入點計算,就算使用高明的秦九韶演算法 每個座標需要o(n)的時間,n個座標就是o(n2),那麼並沒有什麼用處。這時候,單位負根的另乙個性質就得到了體現,我們可以利用分治的思想,將這個過程的時間複雜度降到o(nlogn)。
這就是快速傅利葉變換fft,說白了就是乙個形式轉換函式的加速版本。
首先,為了方便起見,我們需要項數為2的冪次,不妨記為n=2k。研究多項式,有多項式pn的最高次為n-1次,超出原多項式的項係數為0,這個我們在上面討論過。
接下來 我們可以按照奇偶將多項式函式p(x)分成兩部分,即:
p n(x)=odd(x)+even(x)
我們將odd(x)中提出乙個x,那麼我們得到
x * even(x)=even(x)
聯立可以得到:
p n(x)=x * even(x)+even(x)
不難發現,偶次項組成的多項式中,我們可以用x^2來代替x,即得到新的
p n(x)=a
n/2(x
2)+b
n/2(x
2)其中a和b都是項數減半的多項式。
假設我們現在代入x=wn
k(當 k < n/2時),有:
p n(w
nk)=a
n/2(w
nwk)+b
n/2(w
n2k) * x
p n(w
nk)=a
n/2(w
n2k)+b
n/2(w
n2k) * w nk
由單位復根性質可知:w n
2k=w
n/2k即:
p n(w
nk)=a
n/2(w
n/2k)+b
n/2(w
n/2k) * w nk
類似地,當n=k+n/2,我們有:
p n(w
nk+n/2)=a
n/2(w
n/2k)+b
n/2(w
n/2k) * w
nk+n/2
p n(w
nk+n/2)=a
n/2(w
n/2k)-b
n/2(w
n/2k) * w nk
綜上,我們得到兩個遞推公式:
p n(w
nk)=a
n/2(w
n/2k)+b
n/2(w
n/2k) * w nk
pn(w
nk+n/2)=a
n/2(w
n/2k)-b
n/2(w
n/2k) * w nk
從而可以在nlogn時間內進行傅利葉變換。
分治常規的處理方法是遞迴。但是眾所周知,迭代比遞迴快,所以我們將考慮如何迭代來求解該問題。
//求二進位制翻轉數字置
int lim=0;
while((
1<
++lim;
for(
int i=
0;i++i)
這個操作是什麼意思呢?
我們有兩個式子:
p n(w
nk)=a
n/2(w
n/2k)+b
n/2(w
n/2k) * w nk
pn(w
nk+n/2)=a
n/2(w
n/2k)-b
n/2(w
n/2k) * w nk
但是我們又要同時更新這兩個式子,所以怎麼辦呢?
那麼我們另乙個新的t等於後項,然後再去分別更新。有點類似於什麼呢?大概是swap裡面的t的作用。
於是我們就可以在沒有buf的情況下計算fft了。
for
(int l=
2;l<=n;l<<=1)
}}
#include
using
namespace std;
#define cp complex
const
double pi=
acos(-
1.0)
;const
int n=
1005
;int n=
1,res[n]
;string s1,s2;
void
init
(cp *omg,cp *inv)
}void
fft(cp *a,cp *omg)
for(
int l=
2;l<=n;l<<=1)
}}}int
main()
int flag=0;
for(
int i=n;
~i;--i)}if
(flag==
0)cout<<0;
cout<
}}
數學黑科技1 FFT
用途暴力 點值與插值瓶頸 突破口 n次單位復根 有關的定理 群的性質 消去引理 折半引理 求和引理 fft插值一些關於實現的東西 多項式乘法 洛谷3803 模板題 include include include define pi m pi using namespace std struct xu...
FFT實現演算法基礎
本文介紹 fft實現的數字基礎,fft是 dft 離散傅利葉變換 的快速演算法 fft 和dft 的特點是在時域中數值離散 時間離散 可以實現數字量化 在頻域中頻率離散 幅值離散,因此可用於數字裝置中進行運算。以下數字公式及結論詳細推導過程請查閱數字訊號處理。1.dft 的數學公式如下 dft公式可...
具體數學 0 前言
具體數學 是2013年人民郵電出版社出版的圖書,是一本在大學中廣泛使用的經典數學教科書 作者是ronald l.grahamdonald e.knuthoren patashnik。具體數學 電腦科學基礎 第2版 第1章遞迴問題1 1.1 河內塔1 1.2 平面上的直線4 1.3 約瑟夫問題7 習題...