一、基礎知識
Fast演算法是一種基於快速傅里葉變換(FFT)的演算法,可以大幅提高多項式求逆、多項式求值等問題的運算速度。FFT演算法將多項式轉化成點值表示,再通過神奇的分治思想將點值表示轉化成係數表示,進而實現多項式之間的高效運算。
二、演算法流程
根據FFT演算法的思想,fast演算法的主要流程可以分為以下幾步:
1.預處理:
a.選擇一個大於等於n的2的整數次冪m,構造一個大小為m的數組a,並將輸入的n個係數按照升冪排列填充進去。
b.計算m個複數ωn^0,ωn^1,…,ωn^(m-1),其中ωn=exp(2πi/n),並存儲在一個數組w中。
2.變換:
a.在a數組中將原多項式轉化成以點值(nw^0,nw^1,…,nw^(n-1))表示的形式,並存儲在一個數組v中(如果快速求多點值問題,則直接輸入多點值,不需要進行變換)。
b.利用分治思想進行DFT(離散傅里葉變換)操作,將v數組轉化為以係數表示的形式u。
3.逆變換:
a.通過u數組重構多項式。如果需要求解多項式求逆問題,則直接將u數組用於逆變換即可得到所求結果。如果需要快速求多點求值問題,還需將u數組做取模等操作得到最終結果。
三、演算法實現
下面展示一個利用快速傅里葉變換求解多項式之間加、減、乘運算的示例代碼:
#define cd complex<double>
const double PI = acos(-1.0);
int rev[MAXN];
cd a[MAXN], b[MAXN];
inline void FFT(cd *a, int n, int flag)
{
for (int i = 0; i < n; ++ i)
if (i < rev[i]) swap(a[i], a[rev[i]]);
for (int k = 2; k <= n; k <> 1;
cd Wn(cos(2 * PI / k), flag * sin(2 * PI / k));
for (int i = 0; i < n; i += k)
{
cd w(1.0, 0.0);
for (int j = i; j < i + mid; ++ j, w = w * Wn)
{
cd x = a[j], y = w * a[j + mid];
a[j] = x + y; a[j + mid] = x - y;
}
}
}
if (flag == -1) for (int i = 0; i < n; ++ i) a[i] /= n;
}
inline void init(int n)
{
int L = -1;
for (int i = 0; i > 1] >> 1 | (i & 1) <> 1;
solve(l, mid);
int n = 1; while (n <= r - l + 1) n <<= 1;
init(n << 1);
for (int i = l; i <= mid; ++ i) b[i - l] = a[i];
for (int i = mid + 1; i <= r; ++ i) b[r - mid + i - l - 1] = a[i];
FFT(b, n, 1);
for (int i = 0; i < n; ++ i) b[i] *= b[i];
FFT(b, n, -1);
for (int i = l; i <= r; ++ i) a[i] = b[i - l] / (n << 2);
solve(l, mid);
solve(mid + 1, r);
}
四、演算法優化
在實際應用中,fast演算法的性能優化是一個重要的研究方向。以下列舉幾種常見的優化策略:
1.分治優化
在實現多項式乘法時,可以利用卷積定理進行分治,並對每個子問題使用FFT演算法求解。例如將兩個多項式分別拆分成左半部分和右半部分,每個子問題的規模減少一半。這樣可以將時間複雜度優化至O(nlog^2n)。
2.優化FFT實現
FFT演算法中的DFT操作是瓶頸,因此可以通過各種技巧優化DFT實現的效率,例如蝶形運算優化、位逆序置換、遞歸展開、避免重複計算點值等等。在實現時,可以參考一些經典FFT庫的實現進行優化。
3.將mod運算提取
當需要對多項式進行取模、求逆、求導等操作時,可以提前對係數進行取模,在計算過程中進行模運算,最後再對結果做取模即可。由於mod運算開銷較大,這種策略可以帶來深度優化。
4.多項式優化
根據實際需要,可以通過嘗試調整多項式係數的排列順序、引入牛頓迭代優化多項式求解、進行係數約減等方法優化演算法實現。值得注意的是,在優化過程中需要進行多組數據測試進行評估,以避免不必要的副作用。
原創文章,作者:CMYMZ,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/332457.html