两个 200 位十进制数相加:用双指针从末位对齐,把进位写进循环条件逐位模拟竖式加法,最后去前导零。
OJ: roj
题目 ID: 1168
难度:普及-
标签:高精度模拟字符串python
创建: 2026-09-29 22:10
更新: 2026-10-05 04:11
题目描述
求两个不超过 200 位的非负整数的和。输入有两行,每行是一个不超过 200 位的非负整数,可能有多余的前导 0;输出一行,即相加后的结果,结果里不能有多余的前导 0,即如果结果是 342,那么就不能输出为 0342。 输入样例:
text
22222222222222222222
33333333333333333333输出样例:
text
55555555555555555555思路
long long 装不下 200 位的大整数,用高精度竖式加法逐位模拟:把两个数逆序按位存进数组(低位在下标 0),从低位到高位相加并传递进位,全部位算完后还要检查最高位是否产生新进位。输出前去掉结果的前导 0,但全 0 的结果要保留一个 0。
参考代码
Python 版:
python
#!/usr/bin/env python3
# Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
# rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
# rainboy的学习导航网站: https://idx.roj.ac.cn
# create_at: 2026-09-29 22:10
# update_at: 2026-09-29 22:10
import sys
ZERO = ord('0') # 字符数字与数值的偏移量,减法比 int() 逐位转换快也更好读
def add_digits(a: str, b: str) -> str:
"""模拟竖式加法:从最低位对齐逐位相加,进位 carry 只取 0 或 1。"""
i, j, carry = len(a) - 1, len(b) - 1, 0
out: list[str] = [] # 从低位往高位收集,最后整体反转
while i >= 0 or j >= 0 or carry: # 循环条件含 carry:最高位还要再进一次位
s = carry + (ord(a[i]) - ZERO if i >= 0 else 0) + (ord(b[j]) - ZERO if j >= 0 else 0)
out.append(chr(s % 10 + ZERO)) # 本位保留 s 的个位
carry = s // 10 # 进位交给下一轮
i -= 1
j -= 1
return ''.join(reversed(out))
def solve() -> None:
data = iter(sys.stdin.buffer.read().split()) # 两个操作数最多 200 位,可能带前导 0
a, b = next(data), next(data)
# 结果按数值输出:先去掉和的前导 0,全为 0(如 0 + 0)时保留一个 0
print(add_digits(a.decode(), b.decode()).lstrip('0') or '0')
if __name__ == "__main__":
solve()C++ 版(同一算法):
cpp
/**
* Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
* rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
* rainboy的学习导航网站: https://idx.roj.ac.cn
* create_at: 2026-10-05 04:11
* update_at: 2026-10-05 04:11
*/
// 大整数加法:两个不超过 200 位的非负整数相加(输入可能带前导 0)。
#include <cstdio>
#include <cstring>
typedef long long ll;
const int MAXN = 205;
char sa[MAXN], sb[MAXN]; // 两个大整数的字符串形式
int a[MAXN], b[MAXN], c[MAXN]; // a、b 按位存数字(低位在前),c 存结果
ll la, lb, lc; // 三个数的长度
int main() {
scanf("%s%s", sa, sb);
la = strlen(sa);
lb = strlen(sb);
// 逆序逐位转成数字,低位存在下标 0
for (ll i = 0; i < la; i++) a[i] = sa[la - 1 - i] - '0';
for (ll i = 0; i < lb; i++) b[i] = sb[lb - 1 - i] - '0';
// 竖式加法:从低位到高位逐位相加,carry 进位只可能是 0 或 1
ll carry = 0;
ll len = la > lb ? la : lb;
for (ll i = 0; i < len; i++) {
ll s = carry;
if (i < la) s += a[i];
if (i < lb) s += b[i];
c[i] = s % 10;
carry = s / 10;
}
lc = len;
if (carry) { // 最高位还有进位,位数多一位
c[lc] = 1;
lc++;
}
// 去掉结果的前导 0(注意全 0 结果要留一个 0)
while (lc > 1 && c[lc - 1] == 0) lc--;
// 逆序输出即为正确书写顺序
for (ll i = lc - 1; i >= 0; i--) printf("%d", c[i]);
printf("\n");
return 0;
}