【算法专题】高精度之压位

高精度之压位

  • 当数据过大时,此时long long存储不下,因此需要使用vector或者数组存储,然后计算。

  • 一般vector或者数组中每个数据都是一个int,如果每个位置只是存储0~9一位数字的话,比较浪费空间,并且计算也会变慢。因此可以让每个位置存储连续的多位数字,这被称作压位

  • 这里以压4位为例,也就是说:vector或者数组中每个位置存储四个连续的数字。


1. 基本高精度运算

2. 高精度压位运算

  • 压位和不压位的高精度计算存在三点不同点(以下提到的压位都是压4位):

  • (1)存储:不压位的话,vector或者数组中每个数据是0~9;压位以后,每个数据是0~9999

  • (2)计算过程:不压位的话,除数和模数都是10;压位以后,除数和模数都是10000。

  • (3)输出:不压位的话,直接输出;压位的话,需要格式化输出,最高位直接输出即可,其他位都需要输出4位数字,不足的前面补零。

AcWing 791. 高精度加法

问题描述

分析

  • 加减法高精度其实可以压9位,这里为了演示,只压4位。

代码

  • C++
#include <iostream>
#include <vector>

using namespace std;

const int N = 4, M = 1e4;  // 压4位, 改这里注意同时需要该输出格式

vector<int> add(vector<int> &a, vector<int> &b) {
    
    vector<int> c;
    for (int i = 0, t = 0; i < a.size() || i < a.size() || t; i++) {
        if (i < a.size()) t += a[i];
        if (i < b.size()) t += b[i];
        c.push_back(t % M);
        t /= M;
    }
    
    return c;
}

void out(vector<int> a) {
    cout << a.back();
    for (int i = a.size() - 2; i >= 0; i--) printf("%04d", a[i]);
    cout << endl;
}

int main() {
    
    string a, b;
    cin >> a >> b;
    
    vector<int> A, B;
    for (int i = a.size() - 1; i >= 0; i -= N) {
        int st = max(0, i - N + 1), len = i - st + 1;
        A.push_back(stoi(a.substr(st, len)));
    }
    for (int i = b.size() - 1; i >= 0; i -= N) {
        int st = max(0, i - N + 1), len = i - st + 1;
        B.push_back(stoi(b.substr(st, len)));
    }
    
    vector<int> C = add(A, B);
    
    out(C);
    
    return 0;
}

AcWing 792. 高精度减法

问题描述

分析

  • 加减法高精度其实可以压9位,这里为了演示,只压4位。

代码

  • C++
#include <iostream>
#include <vector>

using namespace std;

const int N = 4, M = 1e4;  // 压4位, 改这里注意同时需要该输出格式

bool cmp(vector<int> &a, vector<int> &b) {  // 比较a, b大小
    
    if (a.size() != b.size()) return a.size() > b.size();
    for (int i = a.size() - 1; ~i; i--)
        if (a[i] != b[i])
            return a[i] > b[i];
    return true;
}

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 + M) % M);
        
        if (t < 0) t = 1;
        else t = 0;
    }
    while (c.size() > 1 && c.back() == 0) c.pop_back();
    
    return c;
}

void out(vector<int> a) {
    cout << a.back();
    for (int i = a.size() - 2; i >= 0; i--) printf("%04d", a[i]);
    cout << endl;
}

int main() {
    
    string a, b;
    cin >> a >> b;
    
    vector<int> A, B;
    for (int i = a.size() - 1; i >= 0; i -= N) {
        int st = max(0, i - N + 1), len = i - st + 1;
        A.push_back(stoi(a.substr(st, len)));
    }
    for (int i = b.size() - 1; i >= 0; i -= N) {
        int st = max(0, i - N + 1), len = i - st + 1;
        B.push_back(stoi(b.substr(st, len)));
    }
    
    if (!cmp(A, B)) {
        cout << '-';
        swap(A, B);
    }
    
    vector<int> C = sub(A, B);
    
    out(C);
    
    return 0;
}

AcWing 793. 高精度乘法

问题描述

分析

  • 因为b最大为10000,为了相乘不会超出int的范围,这里只能压4位。

代码

  • C++
#include <iostream>
#include <vector>

using namespace std;

const int N = 4, M = 1e4;  // 压4位, 改这里注意同时需要该输出格式

vector<int> mul(vector<int> &a, int b) {
    vector<int> c;
    for (int i = 0, t = 0; i < a.size() || t; i++) {
        if (i < a.size()) t += a[i] * b;
        c.push_back(t % M);
        t /= M;
    }
    while (c.size() > 1 && c.back() == 0) c.pop_back();
    return c;
}

void out(vector<int> a) {
    printf("%d", a.back());
    for (int i = a.size() - 2; i >= 0; i--) printf("%04d", a[i]);
    cout << endl;
}

int main() {
    
    string a;
    int b;
    cin >> a >> b;
    
    vector<int> A;
    for(int i = a.size() - 1; i >= 0; i -= N) {
        int st = max(0, i - N + 1), len = i - st + 1;
        A.push_back(stoi(a.substr(st, len)));
    }
    
    vector<int> C = mul(A, b);
    
    out(C);
    
    return 0;
}

AcWing 794. 高精度除法

问题描述

分析

  • 演示压4位。

代码

  • C++
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

const int N = 4, M = 1e4;  // 压4位, 改这里注意同时需要该输出格式

vector<int> div(vector<int> a, int b, int &r) {
    
    vector<int> c;
    for (int i = a.size() - 1; i >= 0; i--) {
        r = r * M + 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;
}

void out(vector<int> a) {
    printf("%d", a.back());
    for (int i = a.size() - 2; i >= 0; i--) printf("%04d", a[i]);
    cout << endl;
}

int main() {
    
    string a;
    int b;
    cin >> a >> b;
    
    vector<int> A;
    for(int i = a.size() - 1; i >= 0; i -= N) {
        int st = max(0, i - N + 1), len = i - st + 1;
        A.push_back(stoi(a.substr(st, len)));
    }
    
    int r = 0;
    vector<int> C = div(A, b, r);
    
    out(C);
    cout << r << endl;
    
    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值