Skip to content

11015: 【原1015】高精度乘法

题目

题目描述

author: 刘勤 原OJ链接:https://acm.sjtu.edu.cn/OnlineJudge-old/problem/1015

Description

输入2个整数a和b,输出a*b。

Input Format

输入有两行,第一行a,第二行b。

\(0 \leq a , b \leq 2^{1000}\)。

Output Format

输出只有一行,a*b。

Sample Input

44
3

Sample Output

132

FineArtz's solution

#include <iostream>
#include <string>
#include <vector>
#include <cmath>
using namespace std;

//const int MAXSIZE = 10000;
const double pi = 3.1415926;

class comp{//complex number
    //friend
    friend comp operator +(const comp&, const comp&);
    friend comp operator -(const comp&, const comp&);
    friend comp operator *(const comp&, const comp&);
    friend comp operator /(const comp&, const comp&);
public:
    //constructor
    comp() : x(0.0), y(0.0) {}
    comp(double xx, double yy) : x(xx), y(yy) {};
    comp(const comp &cmp) : x(cmp.x), y(cmp.y) {};

    comp operator ~() const;//conjugation
    comp operator -() const;//minus
    comp& operator =(const comp&);
    double mod() const {return sqrt(x * x + y * y);}
    double smod() const {return x * x + y * y;}
    comp recp() const;
    double x, y;
};
comp comp::operator ~() const {return comp(x, -y);}
comp comp::operator -() const {return comp(-x, -y);}
comp& comp::operator =(const comp &rhs){
    x = rhs.x;
    y = rhs.y;
    return *this;
}
inline comp operator +(const comp &lhs, const comp &rhs){return comp(lhs.x + rhs.x, lhs.y + rhs.y);}
inline comp operator -(const comp &lhs, const comp &rhs){return comp(lhs.x - rhs.x, lhs.y - rhs.y);}
inline comp operator *(const comp &lhs, const comp &rhs){
    return comp(lhs.x * rhs.x - lhs.y * rhs.y, lhs.x * rhs.y + lhs.y * rhs.x);
}
inline comp operator /(const comp &lhs, const comp &rhs){
    double module = rhs.smod();
    return comp((lhs.x * rhs.x - lhs.y * rhs.y) / module, (lhs.x * rhs.y + lhs.y * rhs.x) / module);
}
inline comp comp::recp() const {
    double module = this->smod();
    return comp(x / module, -y / module);
}

class BigInt{
    //friend
    friend ostream& operator <<(ostream&, const BigInt&);
    friend BigInt operator *(const BigInt&, const BigInt&);
public:
    //constructor
    BigInt();
    BigInt(const string&);
    vector<int> data;
    int len;
};
BigInt::BigInt() : len(1), data(0) {}
BigInt::BigInt(const string &s) : len(s.size()){
    for (int i = 1; i <= len; ++i)
        data.push_back(s[len - i] - '0');
}

ostream& operator <<(ostream& os, const BigInt &b){
    for (int i = b.len - 1; i >= 0; --i)
        os << b.data[i];
    return os;
}

vector<comp> FFT(const vector<comp> &f, bool inv = false){
    int len = f.size();
    if (len == 1){
        vector<comp> ret;
        ret.push_back(f[0]);
        return ret;
    }
    vector<comp> f1 , f2;
    for (int i = 0; i < len; i += 2){
        f1.push_back(f[i]);
        f2.push_back(f[i + 1]);
    }
    vector<comp> ret1, ret2, ret;
    ret1 = FFT(f1, inv);
    ret2 = FFT(f2, inv);
    for (int i = 0; i < len; ++i){
        comp w(cos(2.0 * pi * i / len), sin(2.0 * pi * i / len));
        if (inv) w = w.recp();
        comp reti(ret1[i % (len / 2)] + w * ret2[i % (len / 2)]);
        ret.push_back(reti);
    }
    return ret;
}

BigInt operator *(const BigInt &lhs, const BigInt &rhs){
    vector<comp> fx1, fx2;
    int len = max(lhs.len, rhs.len), k = 1;
    while (len > k) k *= 2;
    len = k * 2;
    for (int i = 0; i < len; ++i){
        if (i < lhs.len) fx1.push_back(comp(double(lhs.data[i]), 0.0));
        else fx1.push_back(comp(0.0, 0.0));
    }
    for (int i = 0; i < len; ++i){
        if (i < rhs.len) fx2.push_back(comp(double(rhs.data[i]), 0.0));
        else fx2.push_back(comp(0.0, 0.0));
    }
    vector<comp> y1 = FFT(fx1), y2 = FFT(fx2), y;
    for (int i = 0; i < len; ++i)
        y.push_back(y1[i] * y2[i]);
    vector<comp> fx = FFT(y, 1);
    for (int i = 0; i < len; ++i)
        fx[i].x /= len;
    BigInt ret("");
    for (int i = 0; i < len; ++i)
        ret.data.push_back(round(fx[i].x));
    for (int i = 0; i < len - 1; ++i){
        if (ret.data[i] >= 10){
            ret.data[i + 1] += ret.data[i] / 10;
            ret.data[i] %= 10;
        }
    }
    while (ret.data[len - 1] == 0){
        --len;
        ret.data.erase(ret.data.end() - 1);
    }
    ret.len = len;
    return ret;
}

int main(){
    string s1, s2;
    cin >> s1 >> s2;
    BigInt lhs(s1), rhs(s2);
    cout << lhs * rhs << endl;
    return 0;
}

yyong119's solution

#include <iostream>
#include <cstring>
int a[1000],b[1000],c[2001];
char p[1000],q[1000];
int i,j,k,length,lp,lq;
int main(){
    using namespace std;
    cin>>p>>q; lp=strlen(p); lq=strlen(q);
    for (i=0; i<=lp-1; i++) a[lp-i]=int(p[i]-'0');
    for (i=0; i<=lq-1; i++) b[lq-i]=int(q[i]-'0');
    for (i=1; i<=lp; i++)
        for (j=1; j<=lq; j++){
                c[i+j-1]+=a[i]*b[j];
                c[i+j]+=c[i+j-1]/10;
                c[i+j-1]=c[i+j-1]%10;
        }
    for (i=1; i<=lp+lq+1; i++){
        c[i+1]+=c[i]/10;
        c[i]=c[i]%10;
    }
    for (i=2000; i>=1; i--)
    if (c[i]){
        length=i; break;
    }
    for (i=length; i>=1; i--) cout<<c[i];
    return 0;
}