题解:洛谷 P1601 A+B Problem(高精)

【题目来源】

洛谷:P1601 A+B Problem(高精) - 洛谷(luogu.com.cn)

【题目描述】

高精度加法,相当于 a+b problem,不用考虑负数

【输入】

分两行输入。\(a,b\le 10^{500}\)

【输出】

输出只有一行,代表 \(a+b\) 的值。

【输入样例】

1001
9099

【输出样例】

10100

【核心思想】

  1. 问题分析:计算两个长度可达 500 位的大整数之和。由于整数范围远超 C++ 内置类型(如 long long 最多约 19 位),必须使用高精度加法:将数字按字符串读入,逐位相加并处理进位。本质是模拟手算加法的过程。

  2. 算法选择

    • 字符串/数组存储:将大数以字符串形式读入,逆序存入整型数组(个位在 [0][1] 位置),便于从低位到高位计算。
    • 逐位相加:从低位到高位遍历,对应位相加并加上进位,结果位取模 10,进位为商。
    • 处理最高位进位:若最后进位非零,需增加一位。
    • 复杂度:时间复杂度 \(O(\max(\text{len}_a, \text{len}_b))\),空间复杂度 \(O(\max(\text{len}_a, \text{len}_b))\)
  3. 关键步骤(以 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]
  4. 时间/空间复杂度

    • 时间复杂度:\(O(n)\)\(n\) 是最大位数。
    • 空间复杂度:\(O(n)\)
  5. 高精度模拟

    • 逆序存储:这是高精度运算的标准做法,使得索引 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
posted @ 2026-08-31 09:25  团爸讲算法  阅读(11)  评论(0)    收藏  举报