回文数 「NOIP 1999」

题目描述

若一个数(首位不为零)从左向右读与从右向左读都一样,我们就将其称之为回文数。

例如:给定一个10进制数56,将56加65(即把56从右向左读),得到121是一个回文数。

又如:对于10进制数87:

STEP1:87+78 = 165

STEP2:165+561 = 726

STEP3:726+627 = 1353

STEP4:1353+3531 = 4884

在这里的一步是指进行了一次N进制的加法,上例最少用了4步得到回文数4884。

写一个程序,给定一个N(2<=N<=10或N=16)进制数M,求最少经过几步可以得到回文数。

输入格式

输入有两个数字,N和M

输出格式

输出"STEP="+步数,如果在30步以内(包含30步)不可能得到回文数,则输出“Impossible!”

样例

样例输入

9 87

样例输出

STEP=6

这道题很简单,麻烦的就在于它的数据范围 —— 要用高精度...(我最讨厌)

直接贴代码,没什么好说的 .

Code

#include <iostream>
#include <cstring>

using namespace std;

int n, a[100005], b[100005], ans, i;

void init(int a[]) { // 将字符串s转换成数组a
	string s;
	cin >> n >> s;  // 读入字符串s
	memset(a, 0, sizeof(a)); //数组a清零
	a[0] = s.length(); // 用a[0]计算位数
	for(i=1; i<=a[0]; i++) {
		if(s[a[0]-i] >= '0' && s[a[0]-i] <= '9') a[i] = s[a[0]-i]-'0';
		else a[i] = s[a[0]-i] - 'A' + 10;
	}
}

bool Check(int a[]) { // 判断回文数
	for(i=1; i<=a[0]; i++) { 
		if(a[i] != a[a[0]-i+1]) return false; // 发现不一样的,返回 “ 假 ” 
		return true; // 没有不一样的,返回 “ 真 ” 
	}
}

void Add(int a[]) {
	int i, k;
	for(i=1; i<=a[0]; i++) b[i] = a[a[0]-i+1]; //反序数存入b
	for(i=1; i<=a[0]; i++) a[i] += b[i]; // 逐位相加
	for(i=1; i<=a[0]; i++) {
		a[i + 1] += a[i] / n;
		a[i] %= n; // 处理进位
	}
	if(a[a[0]+1] > 0) a[0]++; // 新的一位,修正 a 的位数 
}

int main() {
	init(a);
	if(Check(a)) {
		cout << "STEP=" << 0 << endl;  // 本来就是一个回文数
		return 0;
	}
	ans = 0; // 初始化
	while(ans <= 30) { // 30 次以内
		ans++; 
		Add(a); // 求和
		if(Check(a)) { // 加起来是否为回文数
			cout << "STEP=" << ans << endl;
			return 0;
		}
	}
	
	cout << "Impossible!\n"; //30 次都没有出现回文数
	
	return 0;
} 

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值