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 中提供...