链接:https://ac.nowcoder.com/acm/contest/19859/G
来源:牛客网
题目描述
若一个数(首位不为零)从左向右读与从右向左读都一样,我们就将其称之为回文数。
例如:给定一个10进制数56,将56加65(即把56从右向左读),得到121是一个回文数。
又如:对于10进制数87:
STEP1:87+78 = 165 STEP2:165+561 = 726
STEP3:726+627 = 1353 STEP4:1353+3531 = 4884
在这里的一步是指进行了一次N进制的加法,上例最少用了4步得到回文数4884。
写一个程序,给定一个N(2<=N<=10或N=16)进制数M(100位之内),求最少经过几步可以得到回文数。如果在30步以内(包含30步)不可能得到回文数,则输出“Impossible!”
进制N>10时,使用大写’A’字母表示10,'B’表示11,…,'E’表示15
输入描述:
两行,分别为N,M
输出描述:
STEP=ans
示例1
输入
9
87
输出
STEP=6
解决方案
#include<stdio.h>
#include<string.h>
int judge(int sm[],int l)
{
int i,j;
for(i=0,j=l;i<=l;i++,j--)
{//首尾相等的数就是回文数
if(sm[i]!=sm[j])//但凡有一对不相等就不是
return 1;
}
return 0;
}
int main()
{
int n;
scanf("%d\n",&n);//输入该数的进制
char s[110];
scanf("%s",s);//该数在100位之内,较大,以字符串形式输入
int len=strlen(s);//计算长度
int m[110]={0};
int i,j,k,l=0;
for(i=0;i<len;i++)
{//将该数的每一位存入整形数组中,其中>='A'的数要转为整形
if(s[i]>='A')
m[i]=s[i]-'A'+10;
else
m[i]=s[i]-'0';
}
int sm[220]={0},cnt=0;
for(k=0;k<30;k++)//三十次得不到回文数就不可能,因此设置范围三十次循环
{
if(cnt!=0)
{//步数不为零,且没有break退出循环说明没得到回文数,将上一非回文数赋回m[]中,继续判断
for(i=0;i<=l;i++)
m[i]=sm[i];
len=l+1;//此时的m数组长度为上一非回文数的长度,由于i=l时为上一非回文数数组的最后一位,所以长度要加一
}
for(i=0,j=len-1;i<len;i++,j--)
sm[i]=m[i]+m[j];//数组首尾相加就是从左向右读与从右向左读的结果
for(i=0;i<210;i++)//注意要小于数组长度,否则会越界
{
if(sm[i]>=n)
{//进制为n,那么逢n进1
sm[i+1]+=sm[i]/n;//不知道逢了多少n就除n,是sm[i+1]进
sm[i]%=n;//进不了位的留在sm[i]中
}
}
for(l=210;l>=0;l--)
{//找到sm数组末尾那个数(因为是倒着存入数组,所以末位不为零)注意这里l要小于数组长度,否则会越界,就无法判断
if(sm[l]!=0)
break;//此时的l就是sm当前的长度
}
if(judge(sm,l))//判断sm是不是回文数
cnt++;//不是的话,步数加一
else
break;//是的话退出循环
}
if(cnt>=30)
printf("Impossible!");//如果判断了30次还没得到那么不可能
else
printf("STEP=%d",cnt+1);//因为最后一步没有cnt++,所以手动加一
return 0;
}