Four large integer arithmetic (vector)

Every four large integer arithmetic, will be timid, although the algorithm contest will be something, but also scattered learned, simple summary before, but things have not been the heart of fragmentation bottom.

So after a lot of calories consumed today, eating several sets of templates finally became its own set of templates summary

Never worry about large integer friends

basis

1. High-precision adder

After the addition is equivalent to high-precision arithmetic addition, make a single-bit adder able to save into

  • A and B are positive integers
  • is the vector index 0 is kept low (all less)
vector<int> add(vector<int> &A,vector<int> &B){
    if(A.size() < B.size()) return add(B,A);//这是为了保证A的位数比B大
    vector<int> C;
    int t = 0;
    for(int i = 0;i < A.size();i++){
        t += A[i];
        if(i < B.size()) t += B[i];
        C.push_back(t % 10);
        t /= 10;
    }
    if(t) C.push_back(t);
    //清除前缀0,为了防止000+0等输入情况
    while(C.size() > 1 && C.back() == 0)C.pop_back();
    return C;
}

2. Precision subtraction

Addition subtraction with the same principle, but also a calculated, using the following tvariable able to save to a higher one by 1

  • A and B must be a positive integer, and returns the results | AB |
vector<int> sub(vector<int> &A,vector<int> &B){
    vector<int> C;
    for(int i= 0,t = 0;i<A.size();i++){
        t = A[i] - t;
        if(i < B.size()) t -= B[i];
        C.push_back((t+10)%10);
        if(t < 0) t = 1;
        else t = 0;
    }
    //清除前缀0
    while(C.size() > 1 && C.back() == 0)C.pop_back();
    return C;
}

3. High accuracy by low

Multiplying each bit precision and low precision numbers, a maximum of 81 because the multiplication, the result of the digital module 10 of the result obtained is a result of the current position, then dividing the result by 10 to save a higher digits

  • A storage positive integer, b is a positive integer also
vector<int> mul(vector<int> &A,int b){
    vector<int> C;
    int t = 0;
    for(int i = 0;i < A.size() || t; i++){
        if(i < A.size()) t += A[i] * b;
        C.push_back(t%10);
        t /= 10;
    }
    return C;
}

4. dividing precision low accuracy

In calculating the division, will be measured from the highest level of the dividend, the results of each bit is the current divisor remainder of the result of the division to do. When one is then calculated (a smaller one, set up the first x-bit), to update the remainder namely remainder * 10 + x bits of the dividend.

  • A storage positive integer, b is also positive integer, r is the remainder
vector<int> div(vector<int> & A,int b,int &r){
    vector<int> C;
    r = 0;
    for(int i = A.size() - 1;i >= 0;i--){
        r = r * 10 + A[i];
        C.push_back(r/b);
        r %= b;
    }
    reverse(C.begin(),C.end());
    while(C.size() > 1 && C.back() == 0)C.pop_back();
    return C;
}

what? Take low accuracy is not enough? In addition to low precision is too low? Then we consider some of the less common case (openjudge Bailian 2980)

The high accuracy by accurately

First talk about multiplication algorithm, from the low to the high ride, in vertical calculations, we are the first multiplier and multiplicand multiplied by each, after the record result, multiplied by the second place, record results and the left one, and so on, until the end of the calculation the last one, and then the results are added, the final outcome.

The calculation process substantially vertical columns and pupils do the same multiplication. In order to facilitate the programming, are not eager to carry processing, but the first results of calculation after all bits, then the processing proceeds from front to back in this position.

A summary of the law: the i-th and j-th bit of the number to another number of a number obtained by multiplying, must be accumulated to the result of the i + j bits. Where i, j are numbers from the lower start counting from zero.
ans [i + j] = a [i] * b [j];

Also to be noted that the carry handle, the current value plus the value of the carry look at whether there are standard figures carry; leading cleared.

vector<int> mul( vector<int> &A, vector<int> &B) {
    int la = A.size(),lb = B.size();
    vector<int> C(la+lb+10,0);//提前申请结果所需的空间
    for(int i=0;i<la;i++){
        for(int j=0;j<lb;j++){
            C[i+j] += A[i] * B[j];
        }
    }
    for(int i=0;i<C.size();i++){
        if(C[i] >= 10){
            C[i + 1] += C[i] / 10;
            C[i] %= 10;
        }
    }
    //处理前导0
    while(C.size() > 1 && C.back() == 0)C.pop_back();
    return C;
}

High precision dividing precision

Integer Division four operations which are the most difficult one. Unlike analog, not imitation manual division operation division, but achieved by subtraction. The basic idea is repeated subtraction, minus up to see how many divisor from the dividend inside, how much business is. Obviously too slow reduced by one, is determined to be a maximum integer number (divisor) of the n-th power of 10 can be reduced.

With 7546 divided by 23, for example:

7546 subtracts first with 23 times 100, i.e. subtracted 2300, 3 can be reduced, and the remaining 646, 300 at this time is the supplier (3 * 300 = 100);

Then 646 minus 10 times 23, i.e., subtracts 230, can be reduced twice, and the remaining 186, then provider 320 is (320 + 10 * 2 = 300);

23 186 then subtracts, 8 can be reduced, the remaining 2, this time is 328 Suppliers (1 * 328 + 8 = 320);

Because the result is less than 2 divided by 23 is 1, and we do not calculate the decimal point, so do not continue to count down.

The results in no decimals:

vector<int> div(vector<int> A,vector<int> B){
    int la = A.size(),lb = B.size();
    int dv = la - lb; // 相差位数
    vector<int> C(dv+1,0);//提前申请结果所需空间
    //将除数扩大,使得除数和被除数位数相等
    reverse(B.begin(),B.end());
    for(int i=0;i<dv;i++)B.push_back(0);
    reverse(B.begin(),B.end());
    lb = la;
    for(int j=0;j<=dv;j++){
        while(!cmp(A,B)){//这里用到一个比较函数,cmp返回的是A是否比B小,此处判断的是A是否大于等于B,该循环当A无法再进行减法时结束
            A = sub(A,B);
            C[dv-j]++;//答案里相应的那一位数字++
        }
        B.erase(B.begin());//缩小被除数
    }
    while(C.size()>1 && C.back() == 0)C.pop_back();
    return C;
}

Well, the base part is over, after the contents of the above good package, we can use more perfect in the race.

Complex

  • The structure is a template on purple borrow books, BASE is an array of the above can save a number. May be understood as a decimal number BASE, WIDTH corresponds to the width BASE
  • Because of the large integer large integer multiplication calculation method with particularity, BASE should be set to 10, WIDTH is set to 1, the corresponding output stream inside sprinf reload function should be controlled to 1 instead of 8
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
struct BigInteger{
    //BASE为vector数组中一位中最大存储的数字,前面都是以10计算的
    //WIDTH为宽度
    static const int BASE = 100000000;
    static const int WIDTH = 8;
    vector<int> s;
    //正数为1,负数为-1
    int flag = 1;
    
    //构造函数
    BigInteger(ll num = 0){*this = num;}
    BigInteger(string str){*this = str;}
    BigInteger(const BigInteger& t){
        this->flag = t.flag;
        this->s = t.s;
    }
    //赋值函数
    BigInteger operator = (ll num){
        s.clear();
        do {
            s.push_back(num % BASE);
            num /= BASE;
        }while(num > 0);
        return *this;
    }
    BigInteger operator = (string &str){
        s.clear();
        int x,len = (str.length()-1)/WIDTH + 1;
        for(int i=0;i<len;i++){
            int end = str.length() - i*WIDTH;
            int start = max(0,end - WIDTH);
            sscanf(str.substr(start,end-start).c_str(),"%d",&x);
            s.push_back(x);
        }
        return *this;
    }

    //基本比较函数 A < B
    bool cmp( vector<int> &A, vector<int> & B){
        if(A.size() != B.size())return A.size() < B.size();
        for(int i=A.size()-1;i>=0;i--){
            if(A[i] != B[i]){
                return A[i] < B[i];
            }
        }
        return false;
    }
    //比较函数如果小于则返回真
    bool operator < ( BigInteger & b){
        return cmp(s,b.s);
    }
    bool operator > ( BigInteger& b){
        return b < *this;
    }
    bool operator <= ( BigInteger &b){
        return !(b < *this);
    }
    bool operator >= ( BigInteger &b){
        return !(*this < b);
    }
    bool operator == ( BigInteger &b){
        return !(b < *this) && (*this < b);
    }
    //基本四则运算
    vector<int> add(vector<int> &A, vector<int> &B);
    vector<int> sub(vector<int> &A, vector<int> &B);
    vector<int> mul(vector<int> &A, int b);
    vector<int> mul(vector<int> &A, vector<int> &B);
    vector<int> div(vector<int> &A, int b);
    vector<int> div(vector<int> A, vector<int> B);

    //重载运算符
    BigInteger operator + (BigInteger &b);
    BigInteger operator - (BigInteger &b);
    BigInteger operator * (BigInteger &b);
    BigInteger operator * (int& b);
    BigInteger operator / (BigInteger & b);
    BigInteger operator / (int b);
};
//重载<<
ostream& operator << (ostream &out,const BigInteger& x) {
    if(x.flag == -1)out << '-';
    out << x.s.back();
    for(int i = x.s.size() - 2; i >= 0;i--){
        char buf[20];
        sprintf(buf,"%08d",x.s[i]);//08d此处的8应该与WIDTH一致
        for(int j=0;j<strlen(buf);j++)out<<buf[j];
    }
    return out;
}
//重载输入
istream& operator >> (istream & in,BigInteger & x){
    string s;
    if(!(in>>s))return in;
    x = s;
    return in;
}
vector<int> BigInteger::add( vector<int> &A, vector<int> &B){
    if(A.size() < B.size())return add(B,A);
    int t = 0;
    vector<int> C;
    for(int i=0;i<A.size();i++){
        if(i<B.size())t += B[i];
        t += A[i];
        C.push_back(t%BASE);
        t /= BASE;
    }
    if(t)C.push_back(t);
    while(C.size() > 1 && C.back() == 0)C.pop_back();
    return C;
}
vector<int> BigInteger::sub( vector<int> &A, vector<int> &B){
    vector<int> C;
    for(int i=0,t=0;i<A.size();i++){
        t = A[i] - t;
        if(i<B.size())t -= B[i];
        C.push_back((t+BASE)%BASE);
        if(t < 0)t = 1;
        else t = 0;
    }
    while(C.size() > 1 && C.back() == 0)C.pop_back();
    return C;
}
vector<int> BigInteger::mul(vector<int> &A,int b){
    vector<int> C;
    int t = 0;
    for(int i = 0;i < A.size() || t; i++){
        if(i < A.size()) t += A[i] * b;
        C.push_back(t%BASE);
        t /= BASE;
    }
    return C;
}
//大数乘大数乘法需要将BASE设置为10,WIDTH设置为1
vector<int> BigInteger::mul( vector<int> &A, vector<int> &B) {
    int la = A.size(),lb = B.size();
    vector<int> C(la+lb+10,0);
    for(int i=0;i<la;i++){
        for(int j=0;j<lb;j++){
            C[i+j] += A[i] * B[j];
        }
    }
    for(int i=0;i<C.size();i++){
        if(C[i] >= BASE){
            C[i + 1] += C[i] / BASE;
            C[i] %= BASE;
        }
    }
    while(C.size() > 1 && C.back() == 0)C.pop_back();
    return C;
}
//大数除以整数
vector<int> BigInteger::div(vector<int> & A,int b){
    vector<int> C;
    int r = 0;
    for(int i = A.size() - 1;i >= 0;i--){
        r = r * 10 + A[i];
        C.push_back(r/b);
        r %= b;
    }
    reverse(C.begin(),C.end());
    while(C.size() > 1 && C.back() == 0)C.pop_back();
    return C;
}
//大数除以大数
vector<int> BigInteger::div(vector<int> A,vector<int> B){
    int la = A.size(),lb = B.size();
    int dv = la - lb; // 相差位数
    vector<int> C(dv+1,0);
    //将除数扩大,使得除数和被除数位数相等
    reverse(B.begin(),B.end());
    for(int i=0;i<dv;i++)B.push_back(0);
    reverse(B.begin(),B.end());
    lb = la;
    for(int j=0;j<=dv;j++){
        while(!cmp(A,B)){
            A = sub(A,B);
            C[dv-j]++;
        }
        B.erase(B.begin());
    }
    while(C.size()>1 && C.back() == 0)C.pop_back();
    return C;
}
BigInteger BigInteger::operator + ( BigInteger & b){
    BigInteger c;
    c.s.clear();
    c.s = add(s,b.s);
    return c;
}

BigInteger BigInteger::operator - ( BigInteger & b) {
    BigInteger c;
    c.s.clear();
    if(*this < b){
        c.flag = -1;
        c.s = sub(b.s,s);
    }
    else{
        c.flag = 1;
        c.s = sub(s,b.s);
    }
    return  c;
}
BigInteger BigInteger::operator *(BigInteger & b){
    BigInteger c;
    c.s = mul(s,b.s);
    return c;
}
BigInteger BigInteger::operator *(int& b){
    BigInteger c;
    c.s = mul(s,b);
    return c;
}
BigInteger BigInteger::operator /(BigInteger & b){
    BigInteger c;
    if(*this < b){
        c.s.push_back(0);
    }
    else{
        c.flag = 1;
        c.s = div(s,b.s);
    }
    return c;
}
BigInteger BigInteger::operator /(int b){
    BigInteger c;
    BigInteger t = b;
    if(*this < t){
        c.s.push_back(0);
    }
    else{
        c.flag = 1;
        c.s = div(s,b);
    }
    return c;
}
int main(){
    BigInteger A,B;
    cin>>A>>B;
    cout<<A+B<<endl;
    cout<<A-B<<endl;
    cout<<A*B<<endl;
    cout<<A/B<<endl;
    return 0;
}

to sum up

Template provides only a positive integer arithmetic, to contain negative integer arithmetic, and requires only a reasonable conversion to, the following table

A B + - * /
+ + |A|+|B| |A|-|B| |A|*|B| |A|/|B|
+ - |A|-|B| |A|+|B| -(|A|*|B|) -(|A|/|B|)
- + |B|-|A| -(|A|+|B|) -(|A|*|B|) -(|A|/|B|)
- - -(|A|+|B|) |B|-|A| |A|*|B| |A|/|B|

[Attachment: References]

  1. https://www.cnblogs.com/wuqianling/p/5387099.html
  2. ACwing algorithm basic course
  3. Introduction to the classic algorithm contest
  4. Little Red Book

Guess you like

Origin www.cnblogs.com/1625--H/p/11141106.html