FFT學習筆記

2022-05-16 11:18:57 字數 3113 閱讀 6656

fft學習筆記

fft,快速傅利葉變換,是一種在\(o(n\log n)\)的時間內計算兩個多項式乘積的演算法。

沒學過的請自行翻閱高中數學選修2-2。

給出乙個多項式 $f(x) = a_0 + a_1x + a_2x^2 + ... + a_nx^n $

係數表示法

就是用乙個係數序列來表達多項式,顯然係數序列和多項式是一一對應的。

\[f(x) = a_0 + a_1x + a_2x^2 + ... + a_nx^n \leftrightarrow f(x) = \

\]點值表示法

點值表示法是把這個多項式看成乙個函式,從上面選取\(n+1\)個點,從而利用這 \(n+1\) 個點來唯一的表示這個函式。

正如解乙個 \(n\) 元方程組需要 \(n+1\) 個方程一樣,這 \(n+1\) 個點的序列顯然也和多項式一一對應。

\[f(x) = a_0 + a_1x + a_2x^2 + ... + a_nx^n \leftrightarrow f(x) = \

\]--------------------分割線--------------------

這兩種表示法各有優劣,係數表示法可以在 \(o(n)\) 的時間內求出乙個 \(f(x_0)\) ,但計算多項式乘法時卻需要 \(o(n^2)\) 的時間,點值表示法則正好相反。所以fft的目的就是利用一些特殊的點,把複雜度均攤一下,變成 \(o(n\log n)\)

這是fft降低複雜度的關鍵,因為單位復根有極為優秀的性質。

定義:對於方程 \(x^n = 1\) 的複數解,稱之為 \(n\) 次單位復根,顯然這樣的單位復根有 \(n\) 個。

其中乙個可以表示為 $ \omega_n = e^} $ 那麼對於每乙個單位復根,有$$ \omega_n^k = e^} $$

而根據尤拉公式,又有:

\[\omega_n = e^} = cos(\frac) + i · sin(\frac)

\]幾何意義:

在乙個單位圓中,把單位圓等分,幾個等分點的座標就是單位復根的向量。

這個圖就可以生動形象表示出來了。

單位根的性質

性質1:\(\omega_n^0 = 1\)

這十分顯然,看圖就知道了。

性質2:\(\omega_n^k = \omega_^\)

可以根據公式證明,或者幾何意義也可直觀理解。

性質3:\(\omega_n^}=-\omega_n^k\)

仍然是代入公式證明即可。

這三個性質就是fft降低複雜度的關鍵了。

對於乙個多項式 $f(x) = a_0 + a_1x + a_2x^2 + ... + a_x^ $

為了便於操作,設 \(n = 2^k\)$ ,不足補0即可。

然後按照奇偶項分類,奇數項提出乙個 \(x\):

\[f(x) = (a_0 + a_2x^2 + ... + a_x^) + x(a_1 + a_3x^2 + ... + a_x^

\]設兩個新的多項式:

\[g(x) = a_0 + a_2x + ... + a_x^}

\]\[h(x) = a_1 + a_3x + ... + a_x^}

\]那麼就可以得到:

\[f(x) = g(x^2)+x·h(x^2)

\]設\(dft(f(x))\)表示對 \(f(x)\) 進行dft操作後得到的點值表示,則:

\[dft(f(x)) = dft(g(x^2))+x·dft(h(x^2))

\]重要的步驟出現了!這時我們依次代入單位復根:

\[dft(f(\omega_n^k)) = dft(g((\omega_n^k)^2))+\omega_n^k·dft(h((\omega_n^k))^2))

\]\[dft(f(\omega_n^k)) = dft(g(\omega_n^))+\omega_n^k·dft(h(\omega_n^))

\]\[dft(f(\omega_n^k)) = dft(g(\omega_}^))+\omega_n^k·dft(h(\omega_}^))

\]同理:

\[dft(f(\omega_n^})) = dft(g(\omega_}^))-x·dft(h(\omega_}^))

\]我們發現,只要我們求出了\(dft(g(\omega_}^))\) 和 \(dft(h(\omega_}^))\),就可以求出 \(dft(f(\omega_n^k))\) 和 \(dft(f(\omega_n^}))\),而這是乙個問題規模不斷變小的子問題,直接遞迴就行了。

複雜度分析:

代入操作要進行 \(n\) 次,花費 \(o(n)\) 的時間,設單次操作複雜度為 \(t(n)\),則有:

\[t(n) = 2t(\frac) +o(n)

\]根據主定理,可得複雜度為 \(o(n \log n)\)

證明過程又臭又長,這裡就不寫了qwq。(參考鏈結)

只介紹演算法:

對於乙個點值序列:\(f(x) = \\)

進行的操作方法和dft類似,只是每次代入\(\frac\)即可。

化簡一下:

\(\frac = e^} = cos(\frac) + i · sin(-\frac)\)

我們注意到這個值和dft代入的值僅僅只有符號上的區別,那麼不妨定義乙個變數\(op\),當 \(op\) 取 \(1\) 時進行 dft操作,取 \(-1\) 就是idft操作。

**實現:

void fft(comp *f,int n,int op) // op=1 -> dft,op=-1 -> idft

comp *g = f,*h = f + n / 2;

fft(g,n / 2,op);fft(h,n / 2,op);//遞迴

comp w(cos(2 * pi / n),sin(2 * pi * op / n)),x(1,0);//單位根

for(int k = 0;k < n / 2;++k)

for(int i = 0;i < n;++i) f[i] = tmp[i];

return;

}

好的最樸素的fft就講完了。

咕咕咕咕咕咕咕咕咕

FFT學習筆記

fft可用於解決一些卷積問題。一般問題形式如下 c a b c i ij 0a i b i j 若把a,b看成兩個次數為n多項式 a x ni 0 a i xi,b x ni 0b i x i 原問題等於兩個多項式相乘,c的次數等於2n 1 乙個次數界為n的多項式a的點值表達為n個點值對所組成的集合...

FFT學習筆記

今天doggu講了,開始覺得這玩意好強啊 後來自己看的時候發現蠻zz wys表示 贊同 所以很多自己覺得遙不可及,一輩子都不可能學會的東西只要慢慢理解,理解好了再把他化為自己的語言,歸到自己的世界裡 就覺得不是很難了,甚至很簡單.當然開始並不是,從 好難啊 到 這麼簡單困大爺我這麼久,之前腦子抽了z...

FFT 學習筆記

f x sum limits a i x i x 0,f x 0 x 1,f x 1 x f x 首先我們要了解複數 即 i sqrt 乙個數有實部和虛部 即 a x y i x,y 原來的實數運算相當於在乙個一維數軸上進行移動,複數則是在二維平面上運動 一句話來說就是摸長相乘,幅角相加 c 中提供...