两个大数相乘 - 高精度FFT
HDU 1402
A * B Problem Plus
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 26545 Accepted Submission(s): 6964
Problem Description
Calculate A * B.
Input
Each line will contain two integers A and B. Process to end of file.
Note: the length of each integer will not exceed 50000.
Note: the length of each integer will not exceed 50000.
Output
For each case, output A * B in one line.
Sample Input
1
2
1000
2
Sample Output
2
2000
思路分析 : 两个 5e4 的多项式相乘,显然最朴素的 n^2 的高精度乘法是过不去的 , 这里可以用 fft , 将两个数看成是多项式即可
有几个坑点 , 0 * 654651 = 0 , 要把首位前面的 0 全去掉
代码示例 :
#include <bits/stdc++.h> using namespace std; #define ll long long const int maxn = 1e5+5; const int maxm = 5e5+5; char s1[maxn], s2[maxn]; const double pi = acos(-1.0); struct Complex{ double x, y; Complex (double _x=0, double _y=0):x(_x), y(_y){} Complex operator -(const Complex &b)const{ return Complex(x-b.x, y-b.y); } Complex operator +(const Complex &b)const{ return Complex(x+b.x, y+b.y); } Complex operator *(const Complex &b)const{ return Complex(x*b.x-y*b.y, x*b.y+y*b.x); } }; Complex x1[maxm], x2[maxm]; void change(Complex y[], int len){ for(int i = 1, j = len/2; i < len-1; i++){ if (i < j) swap(y[i], y[j]); int k = len/2; while(j >= k){ j -= k; k /= 2; } if (j < k) j += k; } } void fft(Complex y[], int len, int on){ change(y, len); for(int h = 2; h <= len; h <<= 1){ Complex wn(cos(-on*2*pi/h), sin(-on*2*pi/h)); for(int j = 0; j < len; j += h){ Complex w(1, 0); for(int k = j; k < j+h/2; k++){ Complex u = y[k]; Complex t = w*y[k+h/2]; y[k] = u+t; y[k+h/2] = u-t; w = w*wn; } } } if (on == -1){ for(int i = 0; i < len; i++) y[i].x /= len; } } vector<int>ans; int sum[maxm]; int main () { while(~scanf("%s%s", s1, s2)){ int l1 = strlen(s1); int l2 = strlen(s2); memset(x1, 0, sizeof(x1)); memset(x2, 0, sizeof(x2)); int len = 1; while(len < (l1+l2-1)) len <<= 1; for(int i = 0; i < l1; i++) x1[i] = Complex((double)(s1[i]-'0'), 0); for(int i = l1; i < len; i++) x1[i] = Complex(0, 0); for(int i = 0; i < l2; i++) x2[i] = Complex((double)(s2[i]-'0'), 0); for(int i = l2; i < len; i++) x2[i] = Complex(0, 0); fft(x1, len, 1); fft(x2, len, 1); for(int i = 0; i < len; i++) x1[i] = x1[i]*x2[i]; fft(x1, len, -1); ans.clear(); ans.resize(l1+l2-1); for(int i = l1+l2-2; i >= 0; i--){ ans[i] += (int)(x1[i].x+0.5); if (i != 0) { ans[i-1] += ans[i]/10; ans[i] %= 10; } else { int temp = ans[0]/10; if(temp != 0){ ans[0] %= 10; ans.insert(ans.begin(), temp); } } } int pos = 0; for(int i = 0; i < l1+l2-1; i++) { pos = i; if (ans[i] != 0) break; } for(int i = pos; i < ans.size(); i++){ printf("%d", ans[i]); } printf("\n"); memset(s1, '\0', sizeof(s1)); memset(s2, '\0', sizeof(s2)); } return 0; } /* 4121 46 1321 46 */
东北日出西边雨 道是无情却有情