一、题目
题目描述
若一个数(首位不为零)从左向右读与从右向左读都一样,我们就将其称之为回文数。
例如:给定一个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
二、C语言完整代码
#include<stdio.h>
#include<string.h>
#include<ctype.h>
void add(char *s,char *s2,int n);
void opposide(char *s,char *s2);
int judge(char *s);
int main()
{
int n;
char s[110],s2[110];
scanf("%d",&n);//输入 n 进制的数 s
getchar();
scanf("%s",s);
int step=0;
if(judge(s)) {printf("STEP=%d",step);return 0;}
while(1)
{
step++;
opposide(s,s2);
add(s,s2,n);
if(judge(s)){printf("STEP=%d",step);return 0;}
if(step==30){printf("Impossible!"); return 0;}
}
}
void opposide(char *s,char *s2)
{
int n=strlen(s);
int i;
for(i=0;i<n;i++)
s2[i]=s[n-i-1];
s2[n]='\0';
}
int judge(char *s) //判断是否回文数,返回值 是1 否0
{
int n=strlen(s);
int i;
for(i=0;i<n/2;i++)
{
if(s[i]!=s[n-i-1]) return 0;
}
return 1;
}
void add(char *s,char *s2,int x)
{
int n=strlen(s);
int c[110]={0};
int i;
for(i=0;i<n;i++)
{
if(isdigit(s[i])) c[n-i-1]+=s[i]-'0';
else c[n-i-1]+=s[i]-'A'+10;
if(isdigit(s2[i])) c[n-i-1]+=s2[i]-'0';
else c[n-i-1]+=s2[i]-'A'+10;
} //此时c数组存储的为倒序
for(i=105;i>=0;i--)
{
if(c[i]!=0) break;
}
n=i+1;
i=0;
while(1)
{
if(c[i]==0&&i>=n) break;
if(c[i]>=x)
{
c[i+1]+=c[i]/x;c[i]%=x;
}
i++;
}
n=i;
for(i=0;i<n;i++)
{
if(c[n-i-1]>=0&&c[n-i-1]<=9) s[i]=c[n-i-1]+'0';
else s[i]=c[n-i-1]+'A'-10;
}
s[n]='\0';
}
三、解析
1.程序可能输入不同进制的数,可能出现当进制大于10时可能出现字母,所以输入的数要作为字符串类型进行输入
scanf("%d",&n);//输入 n 进制的数 s
getchar();
scanf("%s",s);
2.自定义函数judge 判断s字符串是否是回文数
int judge(char *s) //判断是否回文数,返回值 是1 否0
{
int n=strlen(s);
int i;
for(i=0;i<n/2;i++)
{
if(s[i]!=s[n-i-1]) return 0;
}
return 1;
}
注意是字符串s而不是整数int类型的
3.自定义opposide函数 将字符串s1倒序放入字符串s2
void opposide(char *s,char *s2)
{
int n=strlen(s);
int i;
for(i=0;i<n;i++)
s2[i]=s[n-i-1];
s2[n]='\0';
}
4.自定义add函数,将正序字符串s和倒序字符串s2以n进制的数相加
void add(char *s,char *s2,int x)
{
int n=strlen(s);
int c[110]={0};
int i;
for(i=0;i<n;i++)
{
if(isdigit(s[i])) c[n-i-1]+=s[i]-'0';
else c[n-i-1]+=s[i]-'A'+10;
if(isdigit(s2[i])) c[n-i-1]+=s2[i]-'0';
else c[n-i-1]+=s2[i]-'A'+10;
} //此时c数组存储的为倒序
for(i=105;i>=0;i--)
{
if(c[i]!=0) break;
}
n=i+1;
i=0;
while(1)
{
if(c[i]==0&&i>=n) break;
if(c[i]>=x)
{
c[i+1]+=c[i]/x;c[i]%=x;
}
i++;
}
n=i;
for(i=0;i<n;i++)
{
if(c[n-i-1]>=0&&c[n-i-1]<=9) s[i]=c[n-i-1]+'0';
else s[i]=c[n-i-1]+'A'-10;
}
s[n]='\0';
}
这一段自定义函数比长,分开来看
4.1
将s和s2 字符串以数的类型相加存入c数组,c数组为int类型,所以可以存储大于等于10的数,我们在后面再次对c数组进行处理。
我们此时存入c数组按照倒序存入,方便后面的进位计算。
for(i=0;i<n;i++)
{
if(isdigit(s[i])) c[n-i-1]+=s[i]-'0';
else c[n-i-1]+=s[i]-'A'+10;
if(isdigit(s2[i])) c[n-i-1]+=s2[i]-'0';
else c[n-i-1]+=s2[i]-'A'+10;
}
4.2
处理进位,按照进制进位。该位保留余数,整除数给下一位加上。
i=0;
while(1)
{
if(c[i]==0&&i>=n) break;
if(c[i]>=x)
{
c[i+1]+=c[i]/x;c[i]%=x;
}
i++;
}
4.3
最后把c数组存入s字符串就可以了
n=i;
for(i=0;i<n;i++)
{
if(c[n-i-1]>=0&&c[n-i-1]<=9) s[i]=c[n-i-1]+'0';
else s[i]=c[n-i-1]+'A'-10;
}
s[n]='\0';
s是字符串数组,而c是整数型数组,进行转换即可。