大整数加法

GitHub跳转原题关系图返回列表

两个 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;
}