算法基础课——第一章 基础算法(二)

这篇博客介绍了C++中处理大整数(高精度)的方法,包括加减乘除的实现,并给出了相关AcWing题目的解题思路。此外,还讲解了前缀和的概念、作用及其二维形式,以及差分操作及其二维应用,提供了算法实现的基础知识。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

image-20210807031457384

第一章 基础算法(二)


高精度


高精度问题其实只有使用 C++ 编程语言的同学需要关注,使用 java 或 python 编程语言的同学不需要太多关注。因为 java 有大整数类,python 自带的数据范围默认就是无限大,而 C++ 没有相对应的处理大整数运算的数据结构。

高精度的考察主要分为四种: 高 精 度 { 加 法 A + B 减 法 A − B 乘 法 A × a 除 法 A ÷ a 高精度\begin{cases}加法 \quad A+B \\ 减法 \quad A-B \\ 乘法 \quad A \times a \\ 除法 \quad A \div a\end{cases} A+BABA×aA÷a,其中 A , B A,B A,B位数 ⩽ 1 0 6 \leqslant 10^6 106 a ⩽ 10000 a\leqslant 10000 a10000

两个大整数相乘/相除应用的场景不多,并且 A ÷ B A\div B A÷B 即两个大整数相除处理起来非常复杂,所以这里不作考虑。

如何存储大整数?

因为 C++ 中没有能够存储大整数的数据类型的,所以可以将大整数的每一位存在数组当中。

例如有一个大整数 A = 123456789 A=123456789 A=123456789,那么存储到数组当中时,会出现一个问题:**低位在前还是高位在前呢?**即假设有一个数组 s s s,则应该让 s [ 0 ] = 1 s[0]=1 s[0]=1 还是让 s [ 0 ] = 9 s[0]=9 s[0]=9

应该是低位在前,即 s [ 0 ] = 9 , s [ 1 ] = 8 ⋯ s [ 8 ] = 1 s[0]=9,s[1]=8 \cdots s[8]=1 s[0]=9,s[1]=8s[8]=1,这样存储会比较好。因为两个整数相加可能会存在进位,这样进位时会在高位的地方补上数字,而将高位存储到数组的末尾,可以更方便地新增数字。

即用 s [ 0 ] s[0] s[0] 存储整数的个位,用 s [ 1 ] s[1] s[1] 存储整数的十位,以此类推。

高精度加法

高精度加法是模拟人工加法的过程。
1 2 3 + 8 9 2 1 2 \begin{matrix} & 1 & 2 & 3 \\ + & & 8 & 9 \\ \hline & 2 & 1 & 2 \end{matrix} +12281392
所以对于两个大整数 A , B A,B A,B,加法运算就是模拟人工加法的过程,在从低位到高位相加时,考虑进位即可。
A 3 A 2 A 1 A 0 + B 2 B 1 B 0 C 3 C 2 C 1 C 0 \begin{matrix} & A_3 & A_2 & A_1 & A_0 \\ + & & B_2 & B_1 & B_0 \\ \hline & C_3 & C_2 & C_1 & C_0 \end{matrix} +A3C3A2B2C2A1B1C1A0B0C0

C 0 = ( A 0 + B 0 ) % 10 C_0=(A_0+B_0)\%10 C0=(A0+B0)%10

A 0 + B 0 ⩾ 10 A_0+B_0\geqslant 10 A0+B010,则说明需要进位,故 C 1 = ( A 0 + B 0 ) / 10 + ( A 1 + B 1 ) % 10 C_1=(A_0+B_0)/10+(A_1+B_1)\%10 C1=(A0+B0)/10+(A1+B1)%10

一般地,有 C i = ( A i − 1 + B i − 1 ) / 10 + ( A i + B i ) % 10 C_i=(A_{i-1}+B_{i-1})/10+(A_i+B_i)\%10 Ci=(Ai1+Bi1)/10+(Ai+Bi)%10

如果 A i A_i Ai B i B_i Bi 有其中一个不存在,则用 0 0 0 代替即可。

依次类推进行下去,就可以实现模拟人工加法。

AcWing 791. 高精度加法

原题链接

给定两个正整数(不含前导 0 0 0),计算它们的和。

输入格式

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

输出格式

共一行,包含所求的和。

数据范围

1 ≤ 1≤ 1 整数长度 ≤ 1 0 5 ≤10^5 105

输入样例:

12
23

输出样例:

35

时/空限制: 1s / 64MB
来源: 模板题
算法标签:高精度

yxc’s Solution

  • 在 C++ 编程语言中,可以使用vector来代替数组来存储大整数,因为vector自带size函数,可以表示数组的长度,就不需要开额外的变量,存储数组的长度这一信息了。
#include <iostream>
#include <vector>

using namespace std;

const int N = 1e6 + 10;


vector<int> add(vector<int> &A, vector<int> &B)
//这里使用引用&,是为了增加效率,如果不加引用,在调用函数时会将 A 和 B 都复制一遍,会增加耗时
{
   
	vector<int> C;

	int tmp = 0;
	for (int i=0; i < A.size() || i < B.size(); i ++ )
	{
   
		if (i < A.size()) tmp += A[i];
		if (i < B.size()) tmp += B[i];
		C.push_back(tmp % 10);
		tmp /= 10;
	}
	if (tmp) C.push_back(tmp);
	return C;
}

int main()
{
   
	string a, b;
	vector<int> A, B;

	cin >> a >> b; // a = "123456"
	for (int i = a.size() - 1; i >= 0; i -- ) A.push_back(a[i] - '0'); // A = [6, 5, 4, 3, 2, 1]
	for (int i = b.size() - 1; i >= 0; i -- ) B.push_back(b[i] - '0');

	vector<int> C = add(A, B);

	for (int i = C.size() - 1; i >= 0; i -- ) cout << C[i];

	return 0;
}

高精度减法

加减乘除的高精度运算中,大整数的存储方式都是一样的。这样更方便在需要多种运算的题目中统一变量的数据类型。

高精度减法也是模拟人工减法的过程。
1 2 3 − 8 9 3 4 \begin{matrix} & 1 & 2 & 3 \\ - & & 8 & 9 \\ \hline & & 3 & 4 \end{matrix} 1283394
对于两个大整数 A , B A,B A,B,其减法过程也是模拟人工减法的过程,从低位到高位进行相减和借位。
A 3 A 2 A 1 A 0 − B 2 B 1 B 0 C 3 C 2 C 1 C 0 \begin{matrix} \end{matrix}\begin{matrix} & A_3 & A_2 & A_1 & A_0 \\ - & & B_2 & B_1 & B_0 \\ \hline & C_3 & C_2 & C_1 & C_0 \end{matrix} A3C3A2B2C2A1B1C1A0B0C0

C 0 = A 0 − B 0 C_0=A_0-B_0 C0=A0B0

若不够减(如 A i < B i A_i<B_i Ai<Bi)就需要借位,即 A i − B i { ⩾ 0 , A i − B i < 0 , A i − B i + 10 A_i-B_i\begin{cases} \geqslant 0 , & A_i-B_i \\ <0, & A_i-B_i+10\end{cases} AiBi{ 0,<0,AiBiAiBi+10,但若需要借位,则 A i + 1 A_{i+1} Ai+1 就会减去 1 1 1

需要注意的是,高精度减法的模板是默认 A ⩾ B A\geqslant B AB 的,这样可以避免运算结果是负数,如果 A < B A<B A<B,则将它们交换就可以使用高精度减法的模板了。

因为 A − B = − ( B − A ) A-B=-(B-A) AB=(BA),故如果 A − B A-B A

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值