原题
思路
这题看起来复杂,但是如果方法选的好的话还是可以处理的很好的。
自己在debug的过程中看了很多篇blog,还是觉得柳神的代码写的最好。
这里来简单分析一下这一题的思路和要点:
- 首先要做的是补长。如果出现长度不一样的情况的话后面的处理会更加麻烦,所以直接在最开始就给两个数字前面补0到和s一样长,这样就避免了后面的分类讨论处理。
- 在做加法的时候其实和以前做的一些大数加法操作差不多。从后往前处理,每次都要先算一个mod,也就是题目中说的“进制”,用两数相加然后%mod,得到ans中对应位的值(
ans[i] = (s1[i] - '0' + s2[i] - '0' + carry) % mod + '0';
),然后用一个carry(carry = (s1[i] - '0' + s2[i] - '0' + carry) / mod;
)来接收进位,每次做加法的时候要算上carry。 - 最后一个出去的carry不用mod处理,原因是它最大也就是1,不需要考虑进制的问题。
TIPS:
合理利用一些函数和语法可以使代码更精简,例如:
- 利用string的构造函数构造一个“0”字符串:
ss1(s.length() - s1.length(), '0')
,并用加号将两个字符串前后拼接:s1 = ss1 + s1;
。简单有效。 s[i] == '0' ? 10 : (s[i] - '0')
这样的问号表达式是个好东西,具体教程见这里。
代码
这边自己的代码感觉还是太丑了,直接贴柳神的吧。
#include <iostream>
using namespace std;
int main() {
string s, s1, s2, ans;
int carry = 0, flag = 0;
cin >> s >> s1 >> s2;
ans = s;
string ss1(s.length() - s1.length(), '0');
s1 = ss1 + s1;
string ss2(s.length() - s2.length(), '0');
s2 = ss2 + s2;
for(int i = s.length() - 1; i >= 0; i--) {
int mod = s[i] == '0' ? 10 : (s[i] - '0');
ans[i] = (s1[i] - '0' + s2[i] - '0' + carry) % mod + '0';
carry = (s1[i] - '0' + s2[i] - '0' + carry) / mod;
}
if (carry != 0) ans = '1' + ans;
for(int i = 0; i < ans.size(); i++) {
if (ans[i] != '0' || flag == 1) {
flag = 1;
cout << ans[i];
}
}
if (flag == 0) cout << 0;
return 0;
}