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

问题描述
  若一个数(首位不为零)从左向右读与从右向左读都一样,我们就将其称之为回文数。
  例如:给定一个10进制数56,将56加65(即把56从右向左读),得到121是一个回文数
  又如:对于10进制数87:
   S T E P 1 STEP1 STEP1:87+78 = 165 S T E P 2 STEP2 STEP2:165+561 = 726
   S T E P 3 STEP3 STEP3:726+627 = 1353 S T E P 4 STEP4 STEP4:1353+3531 = 4884
  在这里的一步是指进行了一次 N N N进制的加法,上例最少用了4步得到回文数4884。
  写一个程序,给定一个 N N N(2<= N N N<=10或 N N N=16)进制数 M M M(其中16进制数字为0-9与 A − F A-F AF),求最少经过几步可以得到回文数。
  如果在30步以内(包含30步)不可能得到回文数,则输出“ I m p o s s i b l e ! Impossible! Impossible!
输入格式
  两行, N 与 M N与M NM
输出格式
  如果能在30步以内得到回文数,输出“ S T E P = x x STEP=xx STEP=xx”(不含引号),其中 x x xx xx是步数;否则输出一行” I m p o s s i b l e ! Impossible! Impossible!”(不含引号)
样例输入
9
87
样例输出
S T E P = 6 STEP=6 STEP=6

个人思路:

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

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

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;
}
  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值