问题 1161: 【回文数(二)】
题目描述
若一个数(首位不为零)从左向右读与从右向左读都一样,我们就将其称之为回文数。
例如:给定一个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<=16)进制数M,求最少经过几步可以得到回文数。如果在30步以内(包含30步)不可能得到回文数,则输出“Impossible!”
输入共两行
第一行为进制数N(2<=N<=16)
第二行为N进制数M(0<=M<=maxlongint)
输出
共一行,为“STEP=经过的步数”或“Impossible!”
样例输入
9
87
样例输出
STEP=6
原题链接:【回文数(二)】
解题思路:
注意事项: 在这里我用数组从a[0]开始存放数的最低位,a[i]存放高位,便于适应结果数的位数增长,易实现算法
参考代码:
#include<stdio.h>
#include<string.h>
//将输入的字符串转换为int型数的集合
void transform(char s[],int a[]){
int i=0;
while(1){
if(s[i]>='0'&&s[i]<='9')
a[i]=(int)s[i]-48;
else if(s[i]>='a'&&s[i]<='f')
a[i]=(int)s[i]-87;
else if(s[i]>='A'&&s[i]<='F')
a[i]=(int)s[i]-55;
else break;
i++;
}
}
//翻转数字
void reverse(int a[],int b[],int d){
int i;
for(i=0;i<d;i++)
b[i]=a[d-i-1];
}
//相加
void add(int a[],int b[],int *d,int k){
int fla=0,i,c[100];
for(i=0;i<*d;i++){
c[i]=(a[i]+b[i]+fla)%k;
fla=(a[i]+b[i]+fla)/k;
}
if(fla!=0){ //最终进位若为非0,则表示d+1位,不为0有效
c[i]=fla; i++; //重新调整数的位数(加1位)
}
*d=i;
for(i=0;i<*d;i++)
a[i]=c[i]; //将结果数放置到a[]数组
}
//判断回文
int huiwen(int a[],int d){
int i,flag=1;
for(i=0;i<d/2;i++)
if(a[i]!=a[d-i-1]) flag=0;//若存在1对数不相等,则非回文,返回0,否则返1
return flag;
}
int main(){
int a[100],b[100]; //a存初始数(或结果数),b存翻转得到的数
int k,num=0,d; //num记录计算次数,d为数a的长度
char s[100];
scanf("%d%s",&k,s);
transform(s,a);
d=strlen(s);
while(num<=30){
reverse(a,b,d);
add(a,b,&d,k);
num++;
if(huiwen(a,d)) break; //执行到满足回文数时退出循环,成功!
}
if(num!=31) printf("STEP=%d",num);
else printf("Impossible!");
return 0;
}