老题新解|大整数加法

《信息学奥赛一本通》第166题:大整数加法

求两个不超过200位的非负整数的和。

输入:

有两行,每行是一个不超过200位的非负整数,可能有多余的前导0。

输出:

一行,即相加后的结果。结果里不能有多余的前导0,即如果结果是342,那么就不能输

出为0342。

样例输入:

22222222222222222222

33333333333333333333

样例输出:

55555555555555555555

大家好,我是莫小特。

这篇文章给大家带来《信息学奥赛一本通》中的第 166题:大整数加法。

一、题意分析

本题要求对两个不超过 200 位 的非负整数进行加法运算。由于数值范围远超 long long 的表示能力,因此我们不能使用普通整数类型,而应当使用字符数组 + 整数数组的方式来模拟手工加法。

输入两个不超过 200 位的非负整数,输出它们的和。

不能使用普通整型运算,而要自己用数组来模拟加法的全过程。

所以使用 char 数组 albl 来存放输入的两个大数。

由于 cin 不能直接读超长整数,这里用 gets() 读入整行字符串(虽然不安全,但在竞赛中常用来快速处理输入)。

读入后,通过:

cpp 复制代码
la = strlen(al);
lb = strlen(bl);

得到两个字符串的长度,即数字的位数。

程序将字符串反向存入整数数组:

cpp 复制代码
for (int i = 0; i <= la - 1; ++i) 
{
	a[la - i - 1] = al[i] - 48;
}

举个例子,输入 "123" → 存入数组后顺序为 a[0]=3, a[1]=2, a[2]=1 ,即数组中低位在前,高位在后,便于从个位开始做加法。

这样设计的好处是:

可以像我们在纸上竖式加法那样,从个位向高位逐位累加。

二、完成代码

(1)定义变量

cpp 复制代码
int a[2000], b[2000], c[2000];
char al[2000], bl[2000];

三个整数数组分别存放第一个数、第二个数及结果。

两个字符数组存放输入的字符串。

(2)处理输入

cpp 复制代码
gets(al); gets(bl);
la = strlen(al);
lb = strlen(bl);

此处 gets 读入字符串,strlen 计算其长度。

(3)反向存储

cpp 复制代码
for (int i = 0; i <= la - 1; ++i) 
    a[la - i - 1] = al[i] - 48;
for (int i = 0; i <= lb - 1; ++i) 
    b[lb - i - 1] = bl[i] - 48;

这里的 -48 是因为字符 '0' 的 ASCII 值为 48,

减去 48 就可以把字符转为真正的数字。

(4)按位相加

cpp 复制代码
lc = 1; // 从个位开始
while (lc <= la || lc <= lb)
{
    c[lc] = a[lc] + b[lc] + x;  // 当前位相加
    x = c[lc] / 10;             // 判断是否产生进位
    c[lc] %= 10;                // 当前位只保留个位
    lc++;                       // 移动到下一位
}

这里模拟了"手算加法"的核心步骤:

  • 两数同位相加;
  • 加上进位 x
  • 计算新的进位;
  • 再继续下一位。

(5)处理最后进位

c[lc] = x;

如果最后一位相加后仍然有进位,就写入结果的最高位。

(6)去掉前导零

cpp 复制代码
`while (c[lc] == 0 && lc > 1) lc--;`

防止输出类似 000123 的格式。只保留最左边的有效位。

(7)倒序输出

cpp 复制代码
for (int i = lc; i >= 1; --i)
    cout << c[i];
cout << endl;

因为之前是反向存储的,现在倒序输出即可得到正确顺序。

按照样例输入对数据进行验证。

符合样例输出,到网站提交测评。

测试通过!

三、完整代码

该题的完整代码如下:

cpp 复制代码
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

int a[2000], b[2000], c[2000];
char al[2000], bl[2000];

int main()
{
    int la, lb, lc, x = 0;
    gets(al); gets(bl);                  // 读入两个超长整数
    la = strlen(al); lb = strlen(bl);    // 获取两数长度
    for (int i = 0; i <= la - 1; ++i) a[la - i - 1] = al[i] - 48;
    for (int i = 0; i <= lb - 1; ++i) b[lb - i - 1] = bl[i] - 48;
    lc = 1;                              // 从个位开始
    while (lc <= la || lc <= lb)         // 逐位相加
    {
        c[lc] = a[lc] + b[lc] + x;       // 加上进位
        x = c[lc] / 10;                  // 计算新的进位
        c[lc] %= 10;                     // 当前位取个位
        lc++;                            // 移动到下一位
    }
    c[lc] = x;                           // 处理最后的进位
    while (c[lc] == 0 && lc > 1) lc--;   // 去掉前导零
    for (int i = lc; i >= 1; --i) cout << c[i];
    cout << endl;
    return 0;
}

四、总结

这道大整数加法题重点考察的是:

1、大数表示方法:用数组按位存储大数,每个数组元素保存一位(0~9),这样规避了语言内建数值范围的限制。

2、字符串与数字互转 :输入为字符串,需要把字符 '0'~'9' 转换为整数 0~9,以便按位运算。

3、按位加法与进位处理:按位相加并保存进位是核心逻辑,循环要覆盖两个数长度的最大值,最后别忘了处理最高位的进位。

4、输出时去掉前导 0:相加结果不能包含多余的前导 0,输出前需确定最高非零位的位置。

5、代码规范与安全 :建议使用 stringcin/getline 代替 gets,并保持数组下标约定的一致性与可读性。

这类题目是学习数组、字符串和基础算法思想的经典训练题,熟练掌握对今后处理大数问题(乘法、减法、进位/借位问题等)非常有帮助。
---end---

如果你觉得这篇文章对你有帮助,欢迎点赞、收藏、关注我哦!

如果有更好的方法也可以在评论区评论哦,我都会看哒~

我们下集见~

相关推荐
小刘max4 小时前
深入理解队列(Queue):从原理到实践的完整指南
数据结构
过往入尘土4 小时前
服务端与客户端的简单链接
人工智能·python·算法·pycharm·大模型
zycoder.5 小时前
力扣面试经典150题day1第一题(lc88),第二题(lc27)
算法·leetcode·面试
蒙奇D索大5 小时前
【数据结构】考研数据结构核心考点:二叉排序树(BST)全方位详解与代码实现
数据结构·笔记·学习·考研·算法·改行学it
洲覆5 小时前
C++ 模板、泛型与 auto 关键字
开发语言·数据结构·c++
MoRanzhi12035 小时前
15. Pandas 综合实战案例(零售数据分析)
数据结构·python·数据挖掘·数据分析·pandas·matplotlib·零售
智驱力人工智能5 小时前
工厂抽烟检测系统 智能化安全管控新方案 加油站吸烟检测技术 吸烟行为智能监测
人工智能·算法·安全·边缘计算·抽烟检测算法·工厂抽烟检测系统·吸烟监测
千里马-horse6 小时前
Async++ 源码分析7--parallel_reduce.h
开发语言·c++·async++·parallel_reduce
江公望6 小时前
Qt QThread使用方法入门浅解
c++·qt