原题地址
http://poj.org/problem?id=1503
题意:对输入的所有大整数求和。
解题思路
本题是一道涉及高精度整数的水题(超出int/long long int范围的整数),但是这道题没有什么复杂的陷阱,只需要对输入的这些大整数累加求和,小心前后缀即可。
基本思路:用int数组ans的每个元素表示和的每一位(从低到高累加),即对输入的字符串从末尾的input[len-1-i]开始逆序加到ans[i](暂时不进位),最后遍历一遍,遇到进位时向高位进相应位数,即可得到最终结果。
需要当心的地方:
- 由于输入的大整数的长度可能不一,因此用maxLen变量记录最长的字符串,用于输出时确定ans下标的上界。
- 不必在每次处理输入串时就进位,一来比较耗时,二来容易出错(如999+9由于9太短,控制不到十位的进位,而变成9108),可以在最后一起处理进位!
- 可能会出现0052+00036这种多个前导零的情况,最后输出时记得处理;
- 输入的终止条件一定是”0\0”,不能单纯判断第一位是不是0。
另外,考虑到很多学校的机试可以采用Java作答,因此还浅尝了一下Java大整数类BigInteger的滋味,仿佛开挂,如猪添翼~
Java在OJ中的使用详见:http://www.cnblogs.com/gaojupeng/p/4730662.html
AC代码:
C++版
#include <iostream>
#include <cstdlib>
#include <cstring>
#define MAXLEN 105
using namespace std;
int main()
{
char input[MAXLEN]; //每次读入的字符串
int ans[MAXLEN]; //存放计算结果
int i, len, maxLen = 0;
memset(ans, 0, sizeof(ans)); //结果清零
while (cin >> input)
{
if(strcmp(input, "0") == 0) break;
len = strlen(input);
maxLen = (len>maxLen)?len:maxLen; //确定最长的字符串、ans的最大下标
for (i = 0; i < len; ++i)
ans[i] += input[len-1-i]-'0'; //从输入串末尾开始倒序累加到ans
}
for (int i = 0; i<maxLen; ++i) //处理所有位上可能会有的进位
if (ans[i] >= 10) //产生进位
{
ans[i+1] += ans[i]/10;
ans[i] %= 10;
}
int k = maxLen;
while (ans[k] == 0) k--; //除去多余的0,例如0052+0038=0090
while (k >= 0) //输出结果
cout << ans[k--];
cout << endl;
return 0;
}
内存占用: 716Kb 耗时:16ms
算法复杂度:O(n)
Java版
import java.io.*;
import java.util.*;
import java.math.*;
import java.text.*;
public class Main {
public static void main(String[] args)
{
Scanner cin = new Scanner(System.in);
BigInteger x, ans = BigInteger.valueOf(0);
String str;
while (cin.hasNext()) //读到文件尾
{
str = cin.nextLine(); //读取一整行的字符串
if (str.equals("0")) break;
x = new BigInteger(str, 10); //将字符串转为10进制用于初始化大整数
ans = ans.add(x);
}
System.out.println(ans);
cin = null;
}
}
内存占用: 3432Kb 耗时:641ms(毕竟Java…)