一.题目描述:
读入两个不超过25位的火星正整数A和B,计算A+B。需要注意的是:在火星上,整数不是单一进制的,第n位的进制就是第n个素数。例如:地球上的10进制数2,在火星上记为“1,0”,因为火星个位数是2进制的;地球上的10进制数38,在火星上记为“1,1,1,0”,因为火星个位数是2进制的,十位数是3进制的,百位数是5进制的,千位数是7进制的……
输入:
测试输入包含若干测试用例,每个测试用例占一行,包含两个火星正整数A和B,火星整数的相邻两位数用逗号分隔,A和B之间有一个空格间隔。当A或B为0时输入结束,相应的结果不要输出。
输出:
对每个测试用例输出1行,即火星表示法的A+B的值。
样例输入:
1,0 2,1
4,2,0 1,2,0
1 10,6,4,2,1
0 0
样例输出:
1,0,1
1,1,1,0
1,0,0,0,0,0
二.题目分析
刚看到这道题目,我真的是楞了,一心想着38为什么表示成1,1,1,0,真的是百思不得其解,在网上看到一些解题报告,看到了长整数相加...好吧,终于开窍了,我真的是想多了...确实,这是一道长整数加法,这样看来,题目并不难,但是一直WA,自己也测试了大数据,小数据,还是没有找到错误原因,哎,对于不能提供错误样例的评判系统,真的是让人抓狂,这也是我一直热爱USACO的原因。
在此还是贴出我的不知道错因的错误代码,欢迎各位行家指正,不胜感激!先贴出来,以后在改正吧,今天已经找bug精疲力尽...
三.代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
int prime[51];
int IsPrime(int x)
{
int i;
if(x==0||x==1)
return 0;
if(x==2)
return 1;
for(i=2;i<=sqrt(x);i++)
{
if(x%i==0)
return 0;
}
return 1;
}
void Reverse(int *a,int an)
{
int i,j,temp;
for(i=0,j=an-1;i<j;i++,j--)
{
temp=a[i];
a[i]=a[j];
a[j]=temp;
}
}
int add(int *a,int an,int *b,int bn,int *sum)
{
int maxn=an>bn?an:bn,i=an,j=bn,temp;
while(i<maxn)
{
a[i]=0;
i++;
}
while(j<maxn)
{
a[j]=0;
j++;
}
for(i=0;i<=maxn;i++)
sum[i]=0;
for(i=0;i<maxn;i++)
{
temp=sum[i];
sum[i] =(temp+a[i]+b[i])%prime[i];
sum[i+1]=((temp+a[i]+b[i])/prime[i])%prime[i+1];
}
if(sum[i]!=0)
return maxn+1;
return maxn;
}
int main()
{
char str1[60],str2[60];
int a[50],b[50],sum[51],i,j,an,bn,sn,cn=0,temp;
freopen("1016.txt","r",stdin);
for(i=2,j=0;j<51;i++)
{
if(IsPrime(i))
{
prime[j]=i;
j++;
}
}
while(1)
{
scanf("%s%s",str1,str2);
if(strlen(str1)==1&&str1[0]=='0'&&strlen(str2)==1&&str2[0]=='0')
break;
an=0;i=0;
while(1)
{
a[an]=0;
while(str1[i]!=','&&str1[i]!='\0')
{
a[an] *=10;
a[an] +=str1[i]-'0';
i++;
}
an++;
if(str1[i]=='\0')
break;
i++;
}
bn=0;i=0;
while(1)
{
b[bn]=0;
while(str2[i]!=','&&str2[i]!='\0')
{
b[bn] *=10;
b[bn] +=str2[i]-'0';
i++;
}
bn++;
if(str2[i]=='\0')
break;
i++;
}
Reverse(a,an);
Reverse(b,bn);
sn=add(a,an,b,bn,sum);
Reverse(sum,sn);
for(i=0;i<sn-1;i++)
printf("%d,",sum[i]);
printf("%d\n",sum[i]);
}
return 0;
}