【蓝桥杯】 算法训练 回文数

不羁岁月 提交于 2019-12-05 16:48:40

问题描述
  若一个数(首位不为零)从左向右读与从右向左读都一样,我们就将其称之为回文数。
  例如:给定一个10进制数56,将56加65(即把56从右向左读),得到121是一个回文数
  又如:对于10进制数87:
  STEP1STEP1:87+78 = 165 STEP2STEP2:165+561 = 726
  STEP3STEP3:726+627 = 1353 STEP4STEP4:1353+3531 = 4884
  在这里的一步是指进行了一次NN进制的加法,上例最少用了4步得到回文数4884。
  写一个程序,给定一个NN(2<=NN<=10或NN=16)进制数MM(其中16进制数字为0-9与AFA-F),求最少经过几步可以得到回文数。
  如果在30步以内(包含30步)不可能得到回文数,则输出“Impossible!Impossible!
输入格式
  两行,NMN与M
输出格式
  如果能在30步以内得到回文数,输出“STEP=xxSTEP=xx”(不含引号),其中xxxx是步数;否则输出一行”Impossible!Impossible!”(不含引号)
样例输入
9
87
样例输出
STEP=6STEP=6

个人思路:

  • 1)将输入的nn进制数转换为一个数组,里面存放nn进制数的1010进制表示的每一位,然后第i位与第leni+1len - i + 1位相加,得到一个结果后,再转换为nn进制,实现nn进制数正序与逆序相加, 得到一个新的nn进制数;再判断是否是回文数,如果是回文数则输出stepstep,如果不是则step++step++,继续判断
  • 2)将输入的nn进制数转换为一个十进制数,然后再判断该数,首先将该数经retret = retnret * n + ii % nn(ii表示传入的数,i/=ni/=n)公式转换为n进制数(原nn进制的逆序),然后相加得到结果,再返回一个ret==aret == a,如果相等,则正序与逆序的结果应为一致,则表示为回文数

第二种方法说的有点绕,可以举个简单的例子,例如我们输入一个二进制数1100,按照上述的做法就先将其转换为十进制数12(numnum),再将12传入判断,经过上述的公式转换得到3,不相等则该步得到的不是回文数,将ans=12+3=15numans = 12 + 3 = 15赋给num,继续判断

1)

#include <iostream>
#include <string>
#include <cmath>
using namespace std;
int n, step;
string m;
int num[1005];
//判断是否为回文数
bool judge(int x) {
	for (int i = 1; i <= x/2; ++i) {
		if (num[i] != num[x - i + 1])
			return false;
	}
	return true;
}
//n进制数相加
int add(int x) {
	int ans[1005] = {0};
	for (int i = 1; i <= x; ++i) {
		ans[i] = num[i] + num[x - i + 1] + ans[i];
		ans[i+1] += ans[i]/n;
		ans[i] %= n;
	}
	if (ans[x + 1]) {
		x++;
	}
	for (int i = x; i >= 1; --i) {
		num[i] = ans[i];
	}
	return x;
}
int main() {
	cin >> n >> m;
	int len = m.size();
	//转换为十进制
	for (int i = 1; i <= len; ++i) {
		if (m[i - 1] < 65) {
			num[i] = m[i - 1] - '0';
		} else {
			num[i] = m[i - 1] - 'A' + 10;
		}
	}
	while(step <= 30) {
		if (judge(len)) {
			cout << "STEP=" << step << endl;
			return 0;
		}
		step++;
		len = add(len);
 	}
	cout << "Impossible!" << endl;
	return 0;
}

2)

#include <iostream>
#include <string>
using namespace std;
typedef unsigned long long ll;
ll n, step, len, num;
ll ans;
string m;
bool judge(ll a) {
	ll ret = 0;
	//再转换为n进制,此时为原n进制的逆序
	for (ll i = a; i; i /= n) {
		ret = ret * n + i % n;
	}
	ans = ret + a;  //得到和
	return ret == a;  //判断是否为回文数
}
ll ch(char s) {
	if (s >= '0' && s <= '9')
		return s - '0';
	return s - 'A' + 10;
}
int main() {
	cin >> n >> m;
	len = m.size();
	//转换为十进制
	for (int i = 0; i < len; ++i) {
		num = num * n + ch(m[i]);
	}
	while(step <= 30) {
		if (judge(num)) {
			cout << "STEP=" << step << endl;
			return 0;
		}
		num = ans;
		step++;
 	}
	cout << "Impossible!" << endl;
	return 0;
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!