作者: Turbo时间限制: 1S章节: 模拟
若一个数(首位不为零)从左向右读与从右向左读都一样,我们就将其称之为回文数。
我们现在需要产生回文数,步骤如下:
给定一个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(其中16进制数字为0-9与A-F),求最少经过几步可以得到回文数。
如果在30步以内(包含30步)不可能得到回文数,则输出“Impossible!”
两行,N与M
如果能在30步以内得到回文数,输出“STEP=xx”(不含引号),其中xx是步数;否则输出一行”Impossible!”(不含引号)
9
87
STEP=6
基本暴力求解,(没想到直接敲下来没有调试就ac了…)首先判断m是不是回文,不是的话进行相应的操作继续监测,这里对m进行操作的时候,用到了大数操作的思想,处理进位之类的,
详细请见注释。
#include
#include
#include
#include
char word[18]="0123456789ABCDEFG";
int reword(char m[])//判断m是否是回文
{
int len=strlen(m);
int i,j;
for(i=0,j=len-1;j>i;i++,j--)
{
if(m[i]!=m[j])
{
return 0;
}
}
return 1;
}
int main()
{
int n,i,j,flag=0;//n是进制,flag有0,1两种状态,flag为1,m是回文,0不是回文
char m[100];
scanf("%d",&n);
getchar();//吸收回车
gets(m);
for(i=0;i<=30;i++)//循环检测当前的m是否是回文
{
// puts(m);
if(reword(m))//如果是回文 的话直接跳出循环
{
flag=1;
break;
}
int temp[100],sum[100],k=0;//这里temp是同来存放m转化为int型,并且把A,B,C装换成数字
for(j=0;m[j]!='\0';j++)
{
if(m[j]>='0'&&m[j]<='9')
temp[k++]=m[j]-'0';
else if(m[j]>='A'&&m[j]<='G')
temp[k++]=(int)(m[j]-55);
}
for(j=0;j<k;j++)//这里就是相当于原来的数,加倒过来的数,就是首尾相加,存在sum中,但是注意,这里在进位过程中,最高位可能会有进位,所以要在是s[0]这里先空出来,
{
sum[j+1]=temp[j]+temp[k-j-1];
}
int jin=0;
int len=j+1;//因为空了一个是s[0],所以这里sum的长度会比temp长度大1.
for(;j>=1;j--)//这一步就是进位处理,这里sum的存在,就是为了相加之后取余,方便对m进行变换
{
jin=jin+sum[j];
sum[j]=jin%n;
jin=jin/n;
}
sum[0]=jin;
if(sum[0]==0)//如果s[0]上没有进位,从1开始
{
for(k=1;k<len;k++)
{
m[k-1]=word[sum[k]];
}
m[k-1]='\0';
}
else//否则从0开始
{
for(k=0;k<len;k++)
{
m[k]=word[sum[k]];
}
m[k]='\0';
}
}
if(flag==1)
printf("STEP=%d\n",i);
else
printf("Impossible!\n");
return 0;
}