zoukankan      html  css  js  c++  java
  • 2. 大整数乘法

    问题描述

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

    输入形式

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

    输出形式

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

    样例输入

    1234567890

    9876543210

    样例输出

    12193263111263526900

    思路:设两个整数X和Y相乘,先看X,Y位数一致时的情况,

    将四次乘法变成了三次乘法,时间复杂度为T(n)=3T(n/2)+O(n) (n > 1),根据Master定理 。当X,Y位数不一致时,就为位数小的那方补零使其对齐。

    在两数位数差距较大时还可以继续优化。

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<ctime>
    
    using namespace std;
    
    bool compare(string a, string b, int alen, int blen){
        if (alen > blen) return true;
        if (alen < blen) return false;
        if (a >= b) return true;
        else return false;
    }
    
    void fun(string &a, string &b, string &c, string &d){
        int k = 0;
        while(a[k] == '0' && k < a.length()-1)
            a.erase(a.begin() + k);
        k = 0;
        while(b[k] == '0' && k < b.length()-1)
            b.erase(b.begin() + k);
        k = 0;
        while(c[k] == '0' && k < c.length()-1)
            c.erase(c.begin() + k);
        k = 0;
        while(d[k] == '0' && k < d.length()-1)
            d.erase(d.begin() + k);
    }
    
    string subtract(string a, string b){
        int alen = a.length();
        int blen = b.length();
        bool judge = compare(a, b, alen, blen);
        if (!judge) {
            swap(a, b);
            swap(alen, blen);
        }
            
        string result;
        reverse(a.begin(), a.end());
        reverse(b.begin(), b.end());
        //cout << a << ' ' << b << endl; 
        for (int i = 0; i < blen; i++) {
            int res;
            if ((a[i] - '0') - (b[i] - '0') < 0) {
                res = (a[i] - '0') + 10 - (b[i] - '0');
                int j = i + 1;
                while(a[j] == '0' && j < alen) {
                    a[j] = '9'; 
                    j++;
                }    
                a[j] -= 1;
            }
            else res = (a[i] - '0') - (b[i] - '0');
            result += res + '0';    
        }
        result += a.substr(blen, alen - 1);
        if (!judge) result += '-'; 
        reverse(result.begin(), result.end());
        return result;
    }
    
    string add(string a, string b){
        
        int adv = 1;
        if (a[0] == '-' && b[0] != '-') {
            a.erase(a.begin());
            return subtract(b, a);
        }
        if (a[0] != '-' && b[0] == '-') {
            b.erase(b.begin());
            return subtract(a, b);
        }
        if (a[0] == '-' && b[0] == '-') {
            adv = -1;
            a.erase(a.begin());
            b.erase(b.begin());
        }
        int alen = a.length();
        int blen = b.length();
        if (alen < blen) {
            swap(a,b);
            swap(alen, blen);
        }
        
        string s(alen-blen, '0');
        b = s + b;
        //cout << a << ' ' << b << endl;
        int flag = 0;
        string result;
        reverse(a.begin(), a.end());
        reverse(b.begin(), b.end());
        for (int i = 0; i < alen; i++) {
            int res = (a[i] - '0') + (b[i] - '0') + flag;
            result += '0' + (res % 10);
             if (res >= 10) flag = 1;
             else flag = 0;
        }
        if (flag == 1) result += '1';
        //result += a.substr(blen, alen - 1);
        if (adv == -1) result += '-';
        reverse(result.begin(), result.end());
        return result;
    }
    
    string multiply(string a, string b){
        int flag = 1;
        if(a[0] == '-') {
            a.erase(a.begin());
            flag = -flag;
        }
        if(b[0] == '-') {
            b.erase(b.begin());
            flag = -flag;
        }
        int alen = a.length();
        int blen = b.length();
        if (a[0] == '0' || b[0] == '0') return "0";
        if (alen < blen) {
            swap(a,b);
            swap(alen, blen);
        }
        string result;
        reverse(a.begin(), a.end());
        reverse(b.begin(), b.end());
        int res = 0;
        for (int i = 0; i < blen; i++) {
            int adv = 0;
            string parameter;
            for (int j = 0; j < alen; j++) {
                res = (b[i] - '0') * (a[j] - '0') + adv;
                if (res >= 10) adv = res / 10;
                else adv = 0;
                parameter += (res % 10) + '0';
            }
            if (adv > 0) parameter += '0' + adv;
            reverse(parameter.begin(), parameter.end());
            //cout << parameter << endl;
            string s(i, '0');
            if (i == 0) result = parameter;
            else result = add(result, parameter+s);
            //cout << result << endl;
        }
        if (flag == -1) return "-"+result;
        return result;    
    }
    
    //10^n AC+10^(n/2){(A-B)(D-c)+AC+BD}+BD
    //AC BD (A-B)(D-C)
    string solve(string a, string b){
        int flag = 1;
        if(a[0] == '-') {
            a.erase(a.begin());
            flag = -flag;
        }
        if(b[0] == '-') {
            b.erase(b.begin());
            flag = -flag;
        }
        
        int alen = a.length();
        int blen = b.length();
        if (a[alen-1] =='0' && a[0] == '0' || b[blen-1] == '0' && b[0] == '0') return "0";
        if (alen < blen) {
            swap(a, b);
            swap(alen, blen);
        }     
        string s(alen - blen, '0');
        b = s + b;
        int n = alen;
        if(n == 1) {
            if (flag == -1) return '-' + multiply(a, b);
            else return multiply(a, b);    
        }
        int mid = n / 2;
        string A, B, C, D, AC, BD, X;
        A = a.substr(0, mid);
        B = a.substr(mid, n-mid);
        C = b.substr(0, mid);
        D = b.substr(mid, n-mid);
        
        fun(A, B, C, D);
        
        AC = solve(A, C);
        BD = solve(B, D);
        X = solve(subtract(A, B), subtract(D, C));
        //cout << A << ' ' << B << ' ' << C << ' ' << D << endl;
         //cout << AC << ' ' << BD << ' ' << X << endl;
        
        int x = n;
        int y = n / 2;
        if (n % 2) {
            x++; y++;
        }
        
        string s1(x, '0');
        string s2(y, '0');
        
        string result;
        if(flag==-1) result += '-';
        result += add(add(AC+s1, BD), add(X, add(AC, BD))+s2);
        //cout << add(AC+s1, BD) << ' ' << add(AC, BD) << ' ' << add(X, add(AC, BD)) <<' ' << add(X, add(AC, BD))+s2 << endl;
        return result;
    }
    
    int main(){
        string a, b, result;
        cin >> a >> b;
        result = multiply(a, b);
        cout << result;
        return 0;
    }
    View Code
  • 相关阅读:
    申论1
    why factory pattern and when to use factory pattern
    jvm的字符串池
    is assembler instruction and machine instuction atomic
    jvm本身的多线程机制
    final
    java类的加载
    path和classpath的用途
    jar -cmf file1 file2 file3命令
    MANIFEST.MF中的MF是什么意思
  • 原文地址:https://www.cnblogs.com/astonc/p/11661300.html
Copyright © 2011-2022 走看看