PAT Basic 1113. 钱串子的加法
PAT Basic 1113. 钱串子的加法
1. 题目描述:
人类习惯用 10 进制,可能因为大多数人类有 10 根手指头,可以用于计数。这个世界上有一种叫“钱串子”(学名“蚰蜒”)的生物,有 30 只细长的手/脚,在它们的世界里,数字应该是 30 进制的。本题就请你实现钱串子世界里的加法运算。
2. 输入格式:
输入在一行中给出两个钱串子世界里的非负整数,其间以空格分隔。
所谓“钱串子世界里的整数”是一个 30 进制的数字,其数字 0 到 9 跟人类世界的整数一致,数字 10 到 29 用小写英文字母 a 到 t 顺次表示。
输入给出的两个整数都不超过 \(10^5\) 位。
3. 输出格式:
在一行中输出两个整数的和。注意结果数字不得有前导零。
4. 输入样例:
2g50ttaq 0st9hk381
5. 输出样例:
11feik2ir
6. 性能要求:
Code Size Limit
16 KB
Time Limit
400 ms
Memory Limit
64 MB
思路:
题目指出两个整数的最大位数为\(10^5\),且因为是30进制,含有小写英文字母,那就只能将两数存储为字符串。这里宏定义MAX_LEN
为\(10^5+1\),表示最大位数加1个'\0'
的长度,分别定义num1[MAX_LEN]
、num2[MAX_LEN]
和res[MAX_LEN]
存储两个非负整数和求和结果,首先比较两个非负整数的长度,在较短长度的非负整数前补0,然后就是从末位开始对每一位进行求和,做好进位即可。另外需要注意的地方有:
- 加法进位的规则:对于 \(N\) 进制来说,每一位上的数字最大为 \(N-1\) ,那么每一位上的两数相加最大为 \(2(N-1)\) ,考虑到有进位的情况也最多为 \(2(N-1) + 1 = 2N-1<2N\) ,所以两数相加要么没有进位,要么只进位1。
- 根据上述加法进位的规则,结果字符串的长度最多为
MAX_LEN+1
,这里res
的长度定义为MAX_LEN
,最后输出时如果还有进位则在开头补1即可。 - 这里定义标志位
nonzeroFlag
避免结果数字输出前导零。
第一次提交时testpoint3报错,检查后发现题目只保证输入两数非负,testpoint3又只有1分,考虑两数均为0的边界情况,这时候结果应该输出0(但是根据前导零的条件会什么都不输出),加上这一判断后AC。
My Code:
#include <stdio.h>
#include <string.h> // strlen header
#include <ctype.h> // isdigit header
#define MAX_LEN (100000+1) // MAX_LEN + '\0'
// first submit testpoint3 wrong answer
int main(void)
{
char num1[MAX_LEN] = "", num2[MAX_LEN] = "";
char res[MAX_LEN] = "";
int temp1=0, temp2=0, tempSum=0;
int num1Len=0, num2Len=0, resLen=0;
int i=0; // iterator
int carry=0;
int nonzeroFlag=0;
scanf("%s%s", num1, num2);
num1Len = strlen(num1);
num2Len = strlen(num2);
resLen = num1Len;
if(num1Len>num2Len) // add zero to num2
{
resLen = num1Len;
for(i=num1Len-1; i>=num1Len-num2Len; --i) // move the num2
{
num2[i] = num2[i-(num1Len-num2Len)];
}
for(i=num1Len-num2Len-1; i>=0; --i) // add zero in front of num2
{
num2[i] = '0';
}
}
else if(num1Len<num2Len) // add zero to num1
{
resLen = num2Len;
for(i=num2Len-1; i>=num2Len-num1Len; --i) // move the num1
{
num1[i] = num1[i-(num2Len-num1Len)];
}
for(i=num2Len-num1Len-1; i>=0; --i) // add zero in front of num1
{
num1[i] = '0';
}
}
//printf("%s\n%s\n", num1, num2); //output rectified num1, num2
carry = 0;
for(i=resLen-1; i>=0; --i) // add two num
{
// int isdigit(int c);
if(isdigit(num1[i]))
{
temp1 = num1[i] - '0';
}
else // num1[i] is alpha
{
temp1 = num1[i]-'a'+10;
}
if(isdigit(num2[i]))
{
temp2 = num2[i] - '0';
}
else // num2[i] is alpha
{
temp2 = num2[i]-'a'+10;
}
tempSum = temp1+temp2+carry;
carry = tempSum / 30;
if(tempSum%30 < 10) // current bit is 0-9
{
res[i] = tempSum%30 + '0';
}
else // current bit is 'a'-'t'
{
res[i] = tempSum%30 - 10 + 'a';
}
}
if(carry) // if have carry
{
printf("1%s\n", res); // carry only can be 1
}
else // doesn't have carry
{
i=0;
nonzeroFlag=0;
while(res[i]!='\0')
{
if(res[i]!='0' || nonzeroFlag)
{
nonzeroFlag = 1;
printf("%c", res[i]);
}
++i;
}
if(!nonzeroFlag) printf("0\n"); // this fixed testpoint3
else printf("\n");
//printf("%s\n", res);
}
return 0;
}