求两个不超过200位的非负整数的积。
Input
有两行,每行是一个不超过200位的非负整数,没有多余的前导0。
Output
一行,即相乘后的结果。结果里不能有多余的前导0,即如果结果是342,那么就不能输出为0342。
Sample Input
12345678900 98765432100Sample Output
1219326311126352690000
题目分析:
分治。参考《计算机算法设计与分析》(第5版)章节2.4《大整数的乘法》
长度为n的整数X可以划分成前后两段 A和B。
这里需要讨论长度n的奇偶性:
n为偶时,A和B长度均为n/2 ,那么X = A*10^(n/2) + B
n为奇时,A的长度为(n+1)/2,B为n/2,那么X = A*10^(n/2) + B
即A的指数都是由B的长度决定的。
同样,设长度为n2的整数Y可以划分成 C和D。
则X*Y = [A*10^(n1/2) + B] * [C*10^(n2/2) + D] = AC*10^(n1/2+n2/2) + AD*10^(n1/2) + BC*10^(n2/2) + BD
又出现AC、AD、BC、BD 乘积形式,同样的道理,递归解决之。
#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <cmath>
using namespace std;
string product(string a,string b){ //乘积
int len1 = a.length();
int len2 = b.length();
string ans;
int num = 0;
int carry = 0;
if(len1 == 1){
for(int i=len2-1;i>=0;--i){
num = carry + (a[0]-'0')*(b[i]-'0');
carry = num/10;
num %= 10;
ans += (char)(num+'0');
}
if(carry) ans += (char)(carry+'0');
}
else if(len2 == 1){
for(int i=len1-1;i>=0;--i){
num = carry + (b[0]-'0')*(a[i]-'0');
carry = num/10;
num %= 10;
ans += (char)(num+'0');
}
if(carry) ans += (char)(carry+'0');
}
reverse(ans.begin(),ans.end());
return ans;
}
string add(string a,string b,string c,string d){ //求和
string ans;
int len1 = a.length()-1;
int len2 = b.length()-1;
int len3 = c.length()-1;
int len4 = d.length()-1;
int num = 0;
int carry = 0;
while(len1 >= 0 || len2 >= 0 || len3 >= 0 || len4 >= 0){
num = carry;
if(len1 >= 0) num += a[len1]-'0';
if(len2 >= 0) num += b[len2]-'0';
if(len3 >= 0) num += c[len3]-'0';
if(len4 >= 0) num += d[len4]-'0';
carry = num/10;
num %= 10;
ans += (char)(num+'0');
--len1;--len2;--len3;--len4;
}
while(carry){
ans += (char)(carry%10 + '0');
carry /= 10;
}
reverse(ans.begin(),ans.end());
return ans;
}
string solve(string a,string b,int n1,int n2){
if(n1 == 1 || n2 == 1){
return product(a,b);
}
int len1 = (n1+1)/2;
int len2 = (n2+1)/2;
string A,B,C,D;
A.append(a,0,len1);
B.append(a,len1,n1-len1);
C.append(b,0,len2);
D.append(b,len2,n2-len2);
// cout << A << " " << B << " " << C << " " << D << endl;getchar();
string num1 = solve(A,C,len1,len2);
string num2 = solve(A,D,len1,n2-len2);
string num3 = solve(B,C,n1-len1,len2);
string num4 = solve(B,D,n1-len1,n2-len2);
num1.append(n1-len1+n2-len2,'0');
num2.append(n1-len1,'0');
num3.append(n2-len2,'0');
// cout << num1 << " " << num2 << " " << num3 << " " << num4 << endl;getchar();
return add(num1,num2,num3,num4);
}
int main(){
string a,b;
while(cin >> a >> b){
int n1 = a.length();
int n2 = b.length();
cout << solve(a,b,n1,n2) << endl;
// cout << product(a,b) << endl;
// cout << add(a,b,a,b) << endl;
}
return 0;
}