洛谷P1015 [NOIP1999 普及组] 回文数(C++)【回文数,高精度,进制转换】详细解析+代码注释
洛谷P1015 [NOIP1999 普及组] 回文数
题目链接
题目描述
若一个数(首位不为零)从左向右读与从右向左读都一样,我们就将其称之为回文数。
例如:给定一个十进制数 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 \leq N \leq 10\) 或 N=16)进制数 M(100 位之内),求最少经过几步可以得到回文数。如果在 30 步以内(包含 30 步)不可能得到回文数,则输出 Impossible!
。
输入格式
两行,分别是 N ,M。
输出格式
如果能在 30 步以内得到回文数,输出格式形如 STEP=ans
,其中 ans 为最少得到回文数的步数。
否则输出 Impossible!
。
输入输出样例
输入 #1
10
87
输出 #1
STEP=4
题目分析
回文数不用多说,反转后判等。需要注意的有两点,一是本题允许多种进制,二是M的范围可以达到100位,显然要用到高精度了。
解题思路
首先利用字符串接收数字。对字符串进行遍历将其每一位转换为整型数进行存储,这里需要注意的是16进制要区分字母大小写。利用reverse函数实现反转操作。执行相加操作前,首先要判断第一次输入的原数是不是回文数,如果是那么ans为0,程序结束。执行高精度加法时,具体进位逻辑见代码,需注意的是我们执行的是一个数和它的倒序相加,所以向前或向后进位对本题无影响。
代码
#include
#include
#include
#include
using namespace std;
int n,ans;
string str;
vector s1,s2;
int main()
{
cin>>n;
cin>>str;
for(int i=0;i='0'&&str[i]<='9')
s1.push_back(str[i]-'0');
else
if(str[i]>='A') //十六进制需注意字母大小写
s1.push_back(str[i]-'A'+10);
else
s1.push_back(str[i]-'a'+10);
}
s2=s1;
reverse(s1.begin(),s1.end()); //反转函数
if(s1==s2)
{
cout<<"STEP=0";
return 0;
}
while(++ans<=30) //计数
{
int len=s1.size();
for(int i=0;i=n) //某一位大于n时需进行进位操作
{
if(i!=len-1) s1[i+1]++; //每次最多进1,这里由于两数互相倒序,向前进位与向后进位对本题无影响
else s1.push_back(1); //当最后一位满n,进位需要多申请一个位置进位
}
s1[i]%=n; //进位后留下余数
}
s2=s1;
reverse(s1.begin(),s1.end());
if(s1==s2)
{
cout<<"STEP="<