题面
题面描述
若一个数(首位不为零)从左向右读与从右向左读都一样,我们就将其称之为回文数。
例如:给定一个十进制数(56),将(56)加(65)(即把(56)从右向左读),得到(121)是一个回文数。
又如:对于十进制数(87):
STEP1:(87+78 = 165)
STEP2:(165+561 = 726)
STEP3:(726+627 = 1353)
STEP4:(1353+3531) = (4884)
在这里的一步是指进行了一次(N)进制的加法,上例最少用了(4)步得到回文数(4884)。
写一个程序,给定一个(N)((2 le N le 10,N=16))进制数(M)((100)位之内),求最少经过几步可以得到回文数。如果在(30)步以内(包含(30)步)不可能得到回文数,则输出Impossible
!
输入格式
两行,分别是(N,M)。
输出格式
STEP=ans
输入输出样例
输入 #1
10
87
输出 #1
STEP=4
分析
一道不错的模拟题。
回顾一下题面,程序框架应该是这样:
- 输入
m
- 判断
m
是否回文,如果是,输出次数并退出 - 将
m
和m
的倒序相加,存储到m
中 - 还没到
30
次?返回第二步。到了?输出impossible
并返回
但是,对于一个100
位的整数,我们需要用字符串存入。
那么接下来我们要解决一些问题:
如何判断一个数是否回文?
C++
的STL
是其臭名昭著的很大的优势,这不,string
就提供了reverse
函数。(其实string
有很多优点,但美中不足的是他必须用臭名昭著的cin
读入。)
string a;
string tmp=reverse(a.begin(),a.end());
if(tmp==a) ....
如何进行加法?
高精度是个好东西。
关于更多高精度的知识,请自行搜索。
string add(string a,string b)
{
int numa[105],numb[105],numc[105];
int len=a.length(),lenc;
string ret;
for(int i=0;i<len;i++)
{
numa[len-i]=c_to_i(a[i]);
numb[len-i]=c_to_i(b[i]);
}
int d=0;
for(lenc=1;lenc<=len;lenc++)
{
numc[lenc]=numa[lenc]+numb[lenc]+d;
d=numc[lenc]/10;
numc[lenc]%=10;
}
numc[lenc]=d;
while(!numc[lenc]) lenc--;
for(int i=lenc;i;i--)
ret+=i_to_c(numc[i]);
return ret;
}
注:以上代码中的i_to_c
和c_to_i
代表整数转字符和字符转整数。
关于进制
本题其实无必要转进制,只要改一下高精度就可以,把进位部分改成:
for(lenc=1;lenc<=len;lenc++)
{
numc[lenc]=numa[lenc]+numb[lenc]+d;
d=numc[lenc]/k;
numc[lenc]%=k;
}
k
是我定义的进制。
并且在i_to_c
和c_to_i
函数中要加上对16
进制的特殊处理。下面是这两个函数的定义:
int c_to_i(char a)
{
if(isdigit(a)) return a-'0';
return a-'A'+10;
}
char i_to_c(int a)
{
if(a<10) return a+'0';
return a-10+'A';
}
解决了这几个问题,代码就简单了。
代码
#include <bits/stdc++.h>
using namespace std;
y1
string s;
int n;
string my_reverse(string a)
{
string tmp=a;
reverse(tmp.begin(),tmp.end());
return tmp;
}
bool valid(string a)
{
return a==my_reverse(a);
}
int c_to_i(char a)
{
if(isdigit(a)) return a-'0';
return a-'A'+10;
}
char i_to_c(int a)
{
if(a<10) return a+'0';
return a-10+'A';
}
string add(string a,string b,int k)
{
int numa[105],numb[105],numc[105];
int len=a.length(),lenc;
string ret;
for(int i=0;i<len;i++)
{
numa[len-i]=c_to_i(a[i]);
numb[len-i]=c_to_i(b[i]);
}
int d=0;
for(lenc=1;lenc<=len;lenc++)
{
numc[lenc]=numa[lenc]+numb[lenc]+d;
d=numc[lenc]/k;
numc[lenc]%=k;
}
numc[lenc]=d;
while(!numc[lenc]) lenc--;
for(int i=lenc;i;i--)
ret+=i_to_c(numc[i]);
return ret;
}
int main()
{
cin>>n>>s;
for(int i=0;i<=30;i++)
{
if(!valid(s)) s=add(s,my_reverse(s),n);
else
{
printf("STEP=%d
",i);
return 0;
}
}
printf("Impossible!
");
return 0;
}
哦对了,这里特别提醒一个地方,高精度里的一个微小的部分:int d=0;
你看到他了吗?我当初是这么写的:int d;
由于这个变量在函数内,所以不会自动初始化为0
,就因为这个点,我要WA
到自闭。
S
选手就算了,J
选手请特别留意:
这个小问题在Windows
环境下测不出来!
在此感谢
评测记录:
给了链接自行看吧
over.