加载中...

洛谷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<iostream>
#include<string>
#include<vector>
#include<algorithm>

using namespace std;

int n,ans;
string str;
vector<int> s1,s2;

int main()
{
	cin>>n;
	cin>>str;
	for(int i=0;i<str.length();i++)		//将字符串表示的数字每一位转换为整形进行存储 
	{
		if(str[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<len;i++)	//高精度加法 
		{
			s1[i]+=s2[i];	//对应位相加 
			if(s1[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="<<ans;
			return 0;
		}
	}
	cout<<"Impossible!";
	return 0;
}
posted @ 2022-01-24 15:14  我没有bug  阅读(1409)  评论(0编辑  收藏  举报