ACWING 高精度-加减乘除 791 - 794

读取字符串的高精度数字,然后用int数组存上,通过最基础的每位加减乘除和进位等操作完成。

下方给出了所有的操作函数,注意函数的所有输入均为vector 的数组,并且数组存储是从数的低位开始存1000 = [0,0,0,1],和正常存储相反,这是为了便于操作。

791. 高精度加法

题目

791. 高精度加法 - AcWing题库

给定两个正整数,计算它们的和。

输入格式

共两行,每行包含一个整数。

输出格式

共一行,包含所求的和。

数据范围

1 ≤ 整数长度 ≤ 100000

样例输入1
12
23
样例输出1
35
思路

将输入数据按位存储到数组A[] B[], 然后从低位开始遍历相加,大于10进位

// O(n)
// C = A + B, A >= 0, B >= 0
// A B C 数组是从数的低位开始存1000 = [0,0,0,1]
vector<int> add(const vector<int> &A, const vector<int> &B)
{
	if(A.size() < B.size()) return add(B, A); // 保证A数组长
	vector<int> C;
	int carry = 0; // 进位
	int i;
	for(i = 0; i < B.size(); i++)
	{
		carray = A[i] + B[i] + carray;
		C.push_back(carray % 10);
		carray /= 10;
	}
	for(i; i < A.size(); i++)
	{
		carray = A[i] + carray;
		C.push_back(carray % 10);
		carray /= 10;
	}
	if(carray) C.push_back(carray);
	return C;
}

AcWing 792 高精度减法

题目

792. 高精度减法 - AcWing题库

给定两个正整数(不含前导 00),计算它们的差,计算结果可能为负数。

输入格式

共两行,每行包含一个整数。

输出格式

共一行,包含所求的差。

数据范围

1≤整数长度≤105

输入样例:
32
11
输出样例:
21
思路

输入输出方式与高精度加法一样,区别在于减法当前位的结果应该+10之后再%10,判断当前结果如果小于0,应该将当前临时变量变为1,下次计算时减去之前借的1。 注意结尾要去除前导0.

注意控制输入 sub的是A >= 0, B >= 0,A B C 数组是从数的低位开始存1000 = [0,0,0,1],A > B, 注意一定是大减小。

为了实现大减小,可以用cmp函数。

// O(n)
// C = A + B, A >= 0, B >= 0
// A B C 数组是从数的低位开始存1000 = [0,0,0,1]
// A > B, 注意一定是大减小
vector<int> sub(const vector<int> &A, const vector<int> &B)
{
    vector<int> C;
    int carry = 0;
    for(int i = 0; i < A.size(); ++i)
    {
        carry = A[i] - carry;
        if(i < B.size()) carry -= B[i];
        C.push_back((carry + 10) % 10);
        // carry<0 表示从上一位借了一位
        if(carry < 0) carry = 1;
        else carry = 0;
    }
    while (C.size() > 1 && C.back() == 0) C.pop_back();
    return C;
}

// 保证sub是大减小,判断谁打
// A >= 0, B >= 0
// A B 数组是从数的低位开始存1000 = [0,0,0,1]
bool cmp(const vector<int> &A, const vector<int> &B)
{
    if(A.size() != B.size()) return A.size() > B.size();
    for(int i = A.size(); i ; i++) // 从高位开始比较
        if(A[i] != B[i]) return A[i] > B[i];
    return true;
}

AcWing 793 高精度乘法

793. 高精度乘法 - AcWing题库

题目

给定两个非负整数(不含前导 0) A 和 B,请你计算 A×B 的值。

输入格式

共两行,第一行包含整数 A,第二行包含整数 B。

输出格式

共一行,包含 A×B 的值。

数据范围

1≤A的长度≤100000,
0≤B的长度≤10000

输入样例:

2
3

输出样例:

6

思路
  • 高精度乘低精度
    将高精度数组的每一位数乘以低精度数后进位,最终得到的进位再一直向高精度数组延伸填充。注意去除前导零。
// O(nm)
// C = A * B, A >= 0, B >= 0
// A 数组是从数的低位开始存1000 = [0,0,0,1]
// 高精度乘低精度
vector<int> mul(const vector<int> &A, const int b) {
    vector<int> C;
    int carry = 0;
    for (int i = 0; i < A.size() || carry; i++) {
        if (i < A.size()) carry += A[i] * b;
        C.push_back(carry % 10);
        carry /= 10;
    }
    while (C.size() > 1 && C.back() == 0) C.pop_back();
    return C;
}

二层循环乘累加起来,注意递进结果起始位置。在来一个循环遍历结果数组进位。注意去除前导零。

// O(nm)
// C = A * B, A >= 0, B >= 0
// A B 数组是从数的低位开始存1000 = [0,0,0,1]
// 高精度乘高精度
vector<int> mul2(const vector<int> &A, const vector<int> &B) {
    vector<int> C(A.size() + B.size());
    for(int i = 0; i < A.size(); i++)
    {
        for(int j = 0; j < B.size(); i++)
        {
            C[i + j] += A[i] * B[i];
        }
    }
    int carry = 0;
    for(int i = 0; i < C.size(); i++){
        carry = C[i];
        C[i] = carry % 10;
        carry /= 10;
    }
    while (C.size() > 1 && C.back() == 0) C.pop_back();
    return C;
}

AcWing 794 高精度除法

Acwing 794 高精度除法

题目

给定两个非负整数(不含前导 0) A,B,请你计算 A/B 的商和余数。

输入格式

共两行,第一行包含整数 A,第二行包含整数 B。

输出格式

共两行,第一行输出所求的商,第二行输出所求余数。

数据范围

1≤A的长度≤100000,
1≤A的长度≤10000,
B 一定不为 0

输入样例:

7
2

输出样例:

3

思路
  • 高精度除以低精度

从被除数A的高位开始,即A.size() - 1尝试除以b得到每一个商位置的值,循环,将上一次除以的余数结果*10 + 当前A[i]存的被除数 得到此位置的被除数,一直循环除到结束。其实这个过程就是竖式的除法原理。

在这里插入图片描述

// O(n)
// A / b = C ... r, A >= 0, b > 0
// A C 数组是从数的低位开始存1000 = [0,0,0,1]
pair<vector<int>, int> div(const vector<int> &A, int b)
{
    vector<int> C;
    int r = 0; // 余数
    for(int i = A.size() - 1; i; --i)
    {
        r = 10 * r + 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, r};
}
  • 高精度除以高精度

对于两个高精度数,类似高精度除以低精度,还是从A的高位开始尝试除以整个B,这时候A的高位类似上面 r = 10 * r + A[i]; 截取出来一部分很麻烦,可以直接用整个A,让B来对齐,即B向高位移动x位即可,这时候A/B一定只有B的高位非0值的正在除。然后循环移动的x位直到0位,如下图即可计算出。

其中A/B的试除通过循环减直到A < B的时候即可,减成功的次数就是该位的商。循环到最后余下的数即余数

在这里插入图片描述

// O((n-m)*n)
// A / B = C ... R, A >= 0, b > 0
// A B C数组是从数的低位开始存1000 = [0,0,0,1]
pair<vector<int>, vector<int>> div2(vector<int> A, const vector<int> &B) {
    vector<int> C, R; // 商 余数
    int c_size = A.size() - B.size(); // 商的长度
    c_size = c_size > 1 ? c_size : 1; // 防止A比B小短,结果数组最小长度为1
    C.resize(c_size, 0);
    
    // 枚举补0的个数,即将B低位补零使得和每次被除数A的高位对齐
    // eg2: 11111 / 11 --> 11111 / 11000 --> 0111 / 110 --> 01 / 11
    for(int i = c_size; i >= 0; --i)
    {
        vector<int> Bp(i, 0); // 前面补i个0
        for(int x : B) Bp.push_back(x); // Bp后面是B

        // 当A >= Bp 时候就一直通过减来得到除的结果
        int c = 0;
        while(cmp(A, Bp))
        {
            c++;
            A = sub(A, Bp);
        }
        C.push_back(c);
    }
    while (C.size() > 1 && C.back() == 0) C.pop_back(); // 去除前导零
    R = A;
    return {C, R};
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AlwaysDayOne

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值