40. [NOIP1999] 回文数
★☆ 输入文件:huiwen.in
输出文件:huiwen.out
简单对比时间限制:1 s 内存限制:128 MB
【问题描述】
若一个数(首位不为0)从左到右读与从右到左读都是一样,这个数就叫做回文数,例如12521就是一个回文数。
给定一个N进制正整数,把它的各位数字上数字倒过来排列组成一个新数,然后与原数相加,如果是回文数则停止,如果不是,则重复这个操作,直到和为回文数为止。例如:10进制87则有:
STEP1: 87+78=165
STEP2: 165+561=726
STEP3: 726+627=1353
STEP4: 1353+3531=4884
任务:写一个程序,给定一个N(2≤N≤10,N=16)进制数m(10~15用小写字母a~f表示),m的位数上限为20。求最少经过几步可以得到回文数。如果在30步以内(包括30步)不可能得到回文数,则输出“impossible”,否则输出该回文数及生成该回文数的最少步数。
【输入格式】
文件有两行,每行一个数,即N和N进制整数m
【输出格式】
如果输入文件给定的数据在30步以内(包括30步)不可能得到回文数,则输出文件只有一行,即输出“impossible”。
否则输出文件为两行。第一行是由输入文件给定数据生成的回文数,第二行是生成该回文数的最少步数。
【输入输出样例】
输入
10
87
输出
4884
4
水模拟
#include <stdio.h>
#include <string.h>
#define MAXN 100
char str[MAXN];
char strRev[MAXN];
long long stack[MAXN];
int top;
long long GetTenRadix(char *strNum,int rad)
{
int len;
long long num;
len=strlen(strNum);
num=0;
for(int i=0;i<len;i++)
{
if(strNum[i]>='a' && strNum[i]<='z')
{
num=num*rad+(strNum[i]-'a'+10);
}
else
num=num*rad+strNum[i]-'0';
}
return num;
}
void TenToRadix(char *str,long long num,int rad)
{
int k;
top=-1;
while(num)
{
top++;
stack[top]=num%rad;
num/=rad;
}
k=0;
while(top!=-1)
{
if(stack[top]<10)
str[k++]=stack[top]+'0';
else
str[k++]=stack[top]-10+'a';
top--;
}
str[k]=0;
}
bool IsCircle(char *str)
{
int i,j;
i=0;
j=strlen(str)-1;
while(i<j)
{
if(str[i]!=str[j]) return false;
i++;
j--;
}
return true;
}
int main()
{
int m;
int step;
long long num,revnum;
freopen("huiwen.in","r",stdin);
freopen("huiwen.out","w",stdout);
scanf("%d%s",&m,str);
step=0;
while(!IsCircle(str))
{
if(step>=30) break;
num=GetTenRadix(str,m);
int len;
len=strlen(str);
for(int i=0;i<len;i++)
{
strRev[i]=str[len-i-1];
}
revnum=GetTenRadix(strRev,m);
num+=revnum;
TenToRadix(str,num,m);
step++;
}
if(step>=30 && !IsCircle(str))
printf("impossible\n");
else
{
printf("%s\n",str);
printf("%d\n",step);
}
return 0;
}