用 std::string 实现大数加法最稳,因其天然支持索引、长度查询与反向遍历,输入输出零成本,且避免数组越界、vector 初始化/反转/清零等冗余操作。

直接用 std::string 存数字、从低位到高位逐位模拟手算加法,是 C++ 竞赛中实现大数加法最稳、最不易出错的方式。
为什么不用数组或 vector 存单个数字?
数组/vec 虽然也能做,但需要额外维护长度、容易越界;而 std::string 天然支持索引、长度查询、反向遍历,且输入输出零成本(题目基本都给字符串输入)。竞赛里时间紧,string 更少出错。
- 输入直接读成
string a, b,无需拆分 - 计算时用
a[i] - '0'转数字,安全可靠 - 结果仍为
string,可直接cout - 避免
vector初始化、反转、前导零清理等冗余操作
加法核心逻辑:从末尾开始,带进位累加
关键不是“怎么加”,而是“怎么处理进位和边界”。两个字符串长度不同,必须统一从最低位(即 a.back())开始对齐,用两个下标分别倒着走。
- 设
i = a.size()-1,j = b.size()-1,进位carry = 0 - 循环条件是
i >= 0 || j >= 0 || carry(注意:carry 不为 0 也要继续,比如"9"+"1"最后要补一位) - 每次取值:
int da = i >= 0 ? a[i--] - '0' : 0,同理处理b - 当前位结果:
(da + db + carry) % 10,新进位:(da + db + carry) / 10 - 把结果数字转
char推入result字符串,最后reverse(result.begin(), result.end())
常见错误与避坑点
竞赛现场写挂,90% 出在这些地方:
立即学习“C++免费学习笔记(深入)”;
- 忘记处理最终进位 —— 导致
"999"+"1"输出"000"或漏掉"1" - 下标越界没判:比如
i--后立刻用a[i],但此时i已是 -1(有符号整型溢出,行为未定义) - 用
push_back('0' + sum % 10)后忘了reverse,结果是反的 - 误把字符相加:
a[i] + b[j]得到的是 ASCII 和,不是数字和 —— 必须减'0' - 使用
int存中间和:虽然单次最大是9+9+1=19,没问题;但若扩展乘法,这里就得改long long
一个能直接交题的精简版本
以下代码通过了洛谷 P1601、AcWing 791 等典型大数加法题:
string add(string a, string b) {
string res;
int i = a.size() - 1, j = b.size() - 1, carry = 0;
while (i >= 0 || j >= 0 || carry) {
int da = i >= 0 ? a[i--] - '0' : 0;
int db = j >= 0 ? b[j--] - '0' : 0;
int sum = da + db + carry;
res.push_back('0' + sum % 10);
carry = sum / 10;
}
reverse(res.begin(), res.end());
return res;
}
注意:题目保证无前导零,所以不用额外删;若需处理(如输入含前导零),应在计算前用 erase 清理,但竞赛题一般不考这个。
真正难的不是加法本身,而是把这套思路稳定复现出来——尤其是循环条件和下标更新顺序,现场一慌就写反。多默写两遍,比看十篇解析管用。










