多項式乘法

最爱丁珰發表於2024-08-06

FFT主要用於快速求多項式的乘積。多項式的乘積就叫做卷積

\(F\)\(G\)來說,顯然暴力演算法的複雜度是\(O(nm)\),而FFT的時間複雜度為\(O(nlogn)\)

多項式的性質:用任意\(n+1\)個橫座標不同的點,可以唯一確定一個\(n\)次多項式。這個性質叫做多項式的點表示法

證明:設這個多項式\(f=a_nx^n+a_{n-1}x^{n-1}+...+a_1x+a_0\),那麼我們代入\(n+1\)個點可以獲得\(n+1\)個方程,這是\(n+1\)元一次方程,寫出係數行列式就會發現是範德蒙德行列式,由於橫座標不同,所以行列式的值不為\(0\),於是方程有唯一解

\(H=FG\),於是\(H\)\(n+m\)次多項式,我們選取\(n+m+1\)個點代入\(F,G\)之後即可確定\(H\)。這就是點表示法的好處,時間複雜度從\(O(nm)\)降低到了\(O(n+m)\)

於是我們現在要解決的問題是如何快速將一個多項式的係數表示法(也就是我們通常寫出來的多項式)與點表示法互相轉換

下文的\(f(x)=a_{n-1}x^{n-1}+...+a_1x+a_0\)

係數表示法轉點表示法:我們要在取\(n+1\)個特殊點上下功夫,我們取複數域上的單位根

假設\(n\)是偶數,畫出複數域上的單位圓:

image

\(w_n^k\)表示將單位圓等分成\(n\)份,將\(x\)軸逆時針旋轉\(\frac{2πk}{n}\)所得到的複數,其中\(k\)的取值為\([0,n-1]\)。比如上圖,\(w_n^0=1\)\(w_n^3=-i\)

\(w_n^k\)具有如下的性質:

1.\(\forall i\neq j,w_n^i\neq w_n^j\)

2.\(w_n^k=\cos(\frac{2kπ}{n})+i\sin(\frac{2kπ}{n})\)

3.\(w_{2n}^{2k}=w_n^k\)

4.\(w_n^{k+\frac{n}{2}}=-w_n^k\)

現在,我們將\(f\)奇數項和偶數項分開,有\(f=g+h\),其中\(g(x)=a_{n-2}x^{n-2}+a_{n-4}x^{n-4}+...+a_2x^2+a_0,h=a _ {n-1} x ^ {n-1} + a _ {n-3}x^{n-3}+...+a_1x\)

\(g\)中每個\(x\)\(x^2\)代替可設\(φ_1(x)=a_{n-2}x^{\frac{n}{2}-1}+a_{n-4}x^{\frac{n}{2}-2}+...+a_2x+a_0\),將\(h\)提取一個\(x\)並將剩下的式子的\(x\)\(x^2\)代替可得\(φ_2(x)=a_{n-1}x^{\frac{n}{2}-1}+a_{n-3}x^{\frac{n}{2}-2}+...+a_1\),於是\(f(x)=φ_1(x^2)+xφ_2(x^2)\)

現在,設\(k∈[0,\frac{n}{2}-1]\),則\(f(w_n^k)=φ_1(w_n^{2k})+w_n^kφ_2(w_n^{2k})=φ_1(w_{\frac{n}{2}}^{k})+w_n^kφ_2(w_{\frac{n}{2}}^{k}),f(w_n^{k+\frac{n}{2}})=φ_1(w_n^{2k})-w_n^kφ_2(w_n^{2k})=φ_1(w_{\frac{n}{2}}^{k})-w_n^kφ_2(w_{\frac{n}{2}}^{k})\)

也就是說我們要求出將\(w_n^0,w_n^1,...,w_n^{n-1}\)代入\(f\)的值,只需要遞迴求解\(φ_1,φ_2\)即可;一共會劃分\(O(\log n)\)層,每層的總複雜度為\(O(n)\),所以時間複雜度為\(O(n\log n)\)(如果某一次\(n\)為奇數,我們最開始提出一個\(x\)即可)

點表示法轉換為係數表示法:設我們現在已經知道了\((w_n^0,f(w_n^0)),...,(w_n^{n-1},f(w_n^{n-1}))\),我們要求\(f(x)\),則有\(a_k=\frac{\sum_{i=0}^{n-1}f(w_n^{i})(w_n^{-k})^i}{n}\)

證明:

\[\sum_{i=0}^{n-1}f(w_n^{i})(w_n^{-k})^i\\=\sum_{i=0}^{n-1}(\sum_{j=0}^{n-1}a_j(w_n^{i})^j)(w_n^{-k})^i\\=\sum_{i=0}^{n-1}(\sum_{j=0}^{n-1}a_j(w_n^{j})^i)(w_n^{-k})^i\\=\sum_{i=0}^{n-1}\sum_{j=0}^{n-1}a_j(w_n^{j-k})^i\\=\sum_{j=0}^{n-1}a_j\sum_{i=0}^{n-1}(w_n^{j-k})^i\\=na_k \]

,最後一步成立是因為

\[\sum_{i=0}^{n-1}(w_n^{j-k})^i=\begin{cases} n,j=k \\ \frac{1-(w_n^{j-k})^n}{1-w_n^{j-k}}=\frac{1-(w_n^n)^{j-k}}{1-w_n^{j-k}}=\frac{1-1}{1-w_n^{j-k}}=0,j\neq k \end{cases} \]

於是我們設\(\rho(x)=\sum_{i=0}^{n-1}f(w_n^{i})x^{i}\),則我們求出\(\rho(w_n^{0}),\rho(w_n^{-1}),...,\rho(w_n^{-(n-1)})\)即可,這就是上文講的傅立葉正變換(係數表示法轉化為點表示法)

最後講一下實現。實踐證明,如果用遞迴來實現的話,常數是非常大的,所以我們一般利用迭代來實現

影片看到了2:08:00

相關文章