FFT實現高精度乘法
阿新 • • 發佈:2018-12-30
你應該知道$FFT$是用來處理多項式乘法的吧。
那麼高精度乘法和多項式乘法有什麼關係呢?
觀察這樣一個$20$位高精度整數$11111111111111111111$
我們可以把它處理成這樣的形式:$\sum_{i=0}^{19}1\times10^i$
這樣就變成了一個多項式了!
直接上程式碼吧(以$Luogu\ P1919$為例):
#include <cmath> #include <cstdio> #include <algorithm> using std::swap; const int N = 1.4e5 + 10; const double Pi = acos(-1); int n, m, r[N], P, ans[N]; char s[N]; struct C { double x, y; } a[N], b[N]; C operator + (C a, C b) { return (C){ a.x + b.x, a.y + b.y }; } C operator - (C a, C b) { return (C){ a.x - b.x, a.y - b.y }; } C operator * (C a, C b) { return (C){ a.x * b.x - a.y * b.y, a.x * b.y + b.x * a.y }; } void FFT(C f[], int opt) { for(int i = 0; i < n; ++i) if(i < r[i]) swap(f[i], f[r[i]]); for(int len = 1, nl = 2; len < n; len = nl, nl <<= 1) { C rot = (C){cos(Pi / len), opt * sin(Pi / len)}; for(int l = 0; l < n; l += nl) { C w = (C){1, 0}; int r = l + len; for(int k = l; k < r; ++k, w = w * rot) { C x = f[k], y = w * f[k + len]; f[k] = x + y, f[k + len] = x - y; } } } } int main() { scanf("%d%s", &n, s + 1); for(int i = 1; i <= n; ++i) a[i - 1].x = s[n - i + 1] - '0'; scanf("%s", s + 1); for(int i = 1; i <= n; ++i) b[i - 1].x = s[n - i + 1] - '0'; //將字串轉化為多項式的係數 --n; for(m = n + n, n = 1; n <= m; n <<= 1, ++P); for(int i = 0; i < n; ++i) r[i] = (r[i >> 1] >> 1) | ((i & 1) << (P - 1)); //蝴蝶變換FFT FFT(a, 1), FFT(b, 1); for(int i = 0; i < n; ++i) a[i] = a[i] * b[i]; FFT(a, -1); for(int i = 0; i <= m; ++i) ans[i] = (int)(a[i].x / n + .5); for(int i = 0, tmp1, tmp2; i < m; ++i) ans[i + 1] += (ans[i] / 10), ans[i] %= 10; //處理進位(每個係數最多為兩位數) for(int i = m, flag = 0; i >= 0; --i) { if(ans[i] != 0) flag = 1; else if(!flag) continue; printf("%d", ans[i]); }//flag為前導零標記 return puts("") & 0; }
$PS:$程式碼中沒有處理$0\times0$的情況,請讀者自行處理。