[luogu p1015] 回文数
题面
题面描述
若一个数(首位不为零)从左向右读与从右向左读都一样,我们就将其称之为回文数。
例如:给定一个十进制数\(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\n",i);
return 0;
}
}
printf("Impossible!\n");
return 0;
}
哦对了,这里特别提醒一个地方,高精度里的一个微小的部分:int d=0;
你看到他了吗?我当初是这么写的:int d;
由于这个变量在函数内,所以不会自动初始化为0
,就因为这个点,我要WA
到自闭。
S
选手就算了,J
选手请特别留意:
这个小问题在Windows
环境下测不出来!
在此感谢
评测记录:
给了链接自行看吧
over.