C++大整数乘法 分治方法

求两个不超过200位的非负整数的积。

Input

有两行,每行是一个不超过200位的非负整数,没有多余的前导0。

Output

一行,即相乘后的结果。结果里不能有多余的前导0,即如果结果是342,那么就不能输出为0342。

Sample Input

12345678900
98765432100

Sample 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;
}

 

    原文作者:大整数乘法问题
    原文地址: https://blog.csdn.net/qq_39021458/article/details/83015442
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞