两个大数相乘 - 高精度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.
 

 

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
*/

 

posted @ 2018-08-22 10:40  楼主好菜啊  阅读(916)  评论(0编辑  收藏  举报