问题描述
若一个数(首位不为零)从左向右读与从右向左读都一样,我们就将其称之为回文数。
例如:给定一个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 A−F),求最少经过几步可以得到回文数。
如果在30步以内(包含30步)不可能得到回文数,则输出“ I m p o s s i b l e ! Impossible! Impossible!”
输入格式
两行, N 与 M N与M N与M
输出格式
如果能在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 len−i+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 ret∗n + 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=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;
}