题解:洛谷 P1601 A+B Problem(高精)
【题目来源】
洛谷:P1601 A+B Problem(高精) - 洛谷(luogu.com.cn)
【题目描述】
高精度加法,相当于 a+b problem,不用考虑负数。
【输入】
分两行输入。\(a,b\le 10^{500}\)。
【输出】
输出只有一行,代表 \(a+b\) 的值。
【输入样例】
1001
9099
【输出样例】
10100
【核心思想】
-
问题分析:计算两个长度可达 500 位的大整数之和。由于整数范围远超 C++ 内置类型(如
long long最多约 19 位),必须使用高精度加法:将数字按字符串读入,逐位相加并处理进位。本质是模拟手算加法的过程。 -
算法选择:
- 字符串/数组存储:将大数以字符串形式读入,逆序存入整型数组(个位在
[0]或[1]位置),便于从低位到高位计算。 - 逐位相加:从低位到高位遍历,对应位相加并加上进位,结果位取模 10,进位为商。
- 处理最高位进位:若最后进位非零,需增加一位。
- 复杂度:时间复杂度 \(O(\max(\text{len}_a, \text{len}_b))\),空间复杂度 \(O(\max(\text{len}_a, \text{len}_b))\)。
- 字符串/数组存储:将大数以字符串形式读入,逆序存入整型数组(个位在
-
关键步骤(以 vector 版本为例):
- 读入:用
string读入两个大数。 - 逆序存储:
for (int i = a.size()-1; i >= 0; i--) A.push_back(a[i] - '0'),使得个位在A[0]。 - 加法函数:
vector<int> add(vector<int>& A, vector<int>& B):- 初始化
vector<int> C,进位t = 0。 - 循环
i从 0 到max(A.size(), B.size())-1:- 若
i < A.size(),t += A[i]。 - 若
i < B.size(),t += B[i]。 C.push_back(t % 10),t /= 10。
- 若
- 若
t非零,C.push_back(t)。
- 初始化
- 输出:
for (int i = C.size()-1; i >= 0; i--) cout << C[i]。
- 读入:用
-
时间/空间复杂度:
- 时间复杂度:\(O(n)\),\(n\) 是最大位数。
- 空间复杂度:\(O(n)\)。
-
高精度模拟:
- 逆序存储:这是高精度运算的标准做法,使得索引
0对应个位,方便进位传播。 - 进位处理:每一位相加后,结果位为
t % 10,进位为t / 10,最后若进位非零则追加。 - 代码变体:可使用固定数组(如
int a[505])或动态 vector,vector 更灵活。 - 适用场景:高精度运算是算法竞赛的常见基础,用于处理超大整数(如大数加减乘除、阶乘等)。
- 逆序存储:这是高精度运算的标准做法,使得索引
【算法标签】
普及- #高精度
【代码详解】
#include <bits/stdc++.h>
using namespace std;
// 高精度加法函数:计算两个大整数的和
int aplusb(string a, string b, int *c)
{
int j1[505] = {0}, j2[505] = {0}; // j1 和 j2 用于存储两个大整数的每一位数字
int jw = 0; // jw 用于存储进位
int lena = a.length(), lenb = b.length(); // lena 和 lenb 分别表示两个大整数的长度
int len = max(lena, lenb); // len 表示两个大整数中较长的长度
// 将字符串 a 和 b 转换为 int 数组并翻转(方便从低位到高位计算)
for (int i = 0; i < lena; i++) j1[i] = a[lena - i - 1] - '0'; // 将 a 的每一位字符转换为数字并翻转
for (int i = 0; i < lenb; i++) j2[i] = b[lenb - i - 1] - '0'; // 将 b 的每一位字符转换为数字并翻转
// 逐位相加
for (int i = 0; i < len; i++)
{
c[i] = j1[i] + j2[i] + jw; // 当前位的和 = j1[i] + j2[i] + 进位 jw
jw = c[i] / 10; // 计算新的进位
c[i] = c[i] % 10; // 当前位只保留个位数
}
// 如果最高位有进位,需要增加结果的长度
if (jw > 0)
{
c[len] = jw; // 将进位存储到最高位
len++; // 结果长度加 1
}
return len; // 返回结果的位数
}
int main()
{
string a, b; // 用于存储输入的两个大整数
int c[505]; // 用于存储加法结果的每一位数字
int n; // 用于存储加法结果的位数
cin >> a >> b; // 输入两个大整数
// 调用高精度加法函数,计算 a + b 的结果
n = aplusb(a, b, c);
// 输出结果(从高位到低位)
for (int i = n - 1; i >= 0; i--)
cout << c[i];
return 0;
}
#include <iostream>
using namespace std;
const int N = 505; // 最大位数
int a[N], b[N], c[N]; // 数组存储大数,a[1]是个位
int la, lb, lc; // 数组a、b、c的实际长度
// 高精度加法函数:a + b = c
void add(int a[], int b[], int c[])
{
for (int i = 1; i <= lc; i++) // 从个位开始逐位相加
{
c[i] += a[i] + b[i]; // 当前位相加,包括之前的进位
c[i + 1] += c[i] / 10; // 计算进位
c[i] %= 10; // 保留个位
}
if (c[lc + 1]) // 处理最高位的进位
{
lc++; // 长度加1
}
}
int main()
{
// 输入两个大数
string sa, sb;
cin >> sa >> sb;
// 计算长度
la = sa.size();
lb = sb.size();
lc = max(la, lb); // 结果的最大可能长度
// 将字符串逆序存储到数组中
// 个位存储在a[1]、b[1]
for (int i = 1; i <= la; i++)
{
a[i] = sa[la - i] - '0'; // 逆序存储
}
for (int i = 1; i <= lb; i++)
{
b[i] = sb[lb - i] - '0'; // 逆序存储
}
// 执行高精度加法
add(a, b, c);
// 输出结果,逆序输出(从最高位到最低位)
for (int i = lc; i >= 1; i--)
{
printf("%d", c[i]);
}
return 0;
}
#include <bits/stdc++.h>
using namespace std;
// 定义字符串存储输入的大数
string a, b;
// 使用vector存储大数的每一位,方便动态调整大小
vector<int> A, B;
// 高精度加法函数
vector<int> add(vector<int> &A, vector<int> &B)
{
vector<int> C; // 结果数组
int t = 0; // 进位,初始为0
// 从个位开始逐位相加
for (int i = 0; i < A.size() || i < B.size(); i++)
{
// 如果A还有当前位,加上A的当前位
if (i < A.size()) t += A[i];
// 如果B还有当前位,加上B的当前位
if (i < B.size()) t += B[i];
// 当前位的和模10,得到该位的结果
C.push_back(t % 10);
// 计算进位
t /= 10;
}
// 处理最后的进位
if (t) C.push_back(1);
return C;
}
int main()
{
// 输入两个大数
cin >> a >> b;
// 将字符串逆序转换为vector,个位在前
for (int i = a.size() - 1; i >= 0; i--)
A.push_back(a[i] - '0');
for (int i = b.size() - 1; i >= 0; i--)
B.push_back(b[i] - '0');
// 计算和
auto C = add(A, B);
// 逆序输出结果,从最高位到最低位
for (int i = C.size() - 1; i >= 0; i--)
printf("%d", C[i]);
return 0;
}
【运行结果】
1001
9099
10100
浙公网安备 33010602011771号