#温馨提示:此文章使用的是MD编辑器,在小程序上查看可能会出现乱码,敬请谅解
题目介绍
题目描述
本题难度:普及-
算法标签:模拟 高精度
若一个数(首位不为零)从左向右读与从右向左读都一样,我们就将其称之为回文数。
例如:给定一个十进制数 56 56 56,将 56 56 56 加 65 65 65(即把 56 56 56 从右向左读),得到 121 121 121 是一个回文数。
又如:对于十进制数 87 87 87:
STEP1:
87
+
78
=
165
87+78=165
87+78=165
STEP2:
165
+
561
=
726
165+561=726
165+561=726
STEP3:
726
+
627
=
1353
726+627=1353
726+627=1353
STEP4:
1353
+
3531
=
4884
1353+3531=4884
1353+3531=4884
在这里的一步是指进行了一次 N N N 进制的加法,上例最少用了 4 4 4 步得到回文数 4884 4884 4884。
写一个程序,给定一个
N
N
N(
2
≤
N
≤
10
2 \le N \le 10
2≤N≤10 或
N
=
16
N=16
N=16)进制数
M
M
M(
100
100
100 位之内),求最少经过几步可以得到回文数。如果在
30
30
30 步以内(包含
30
30
30 步)不可能得到回文数,则输出 Impossible!
。
输入格式
两行,分别是 N N N, M M M。
输出格式
如果能在
30
30
30 步以内得到回文数,输出格式形如 STEP=ans
,其中
ans
\text{ans}
ans 为最少得到回文数的步数。
否则输出 Impossible!
。
样例 #1
样例输入 #1
10 \texttt{10} 10
87 \texttt{87} 87
样例输出 #1
STEP=4 \texttt{STEP=4} STEP=4
题解代码及思路
本题是一道考察高精度知识的题目。
由于数据范围过大,我们需要使用高精度来完成。
本代码使用如下方法:
-
定义常量 S S S 为缓冲区大小,以及变量 n n n 存储进制数、 a [ ] a[\,] a[] 作为辅助数组、 l l l 存储当前处理的数字长度、 c [ ] c[\,] c[] 存储原始输入的数字字符数组、 d [ ] d[\,] d[] 用于临时存储反向读取的数字。
-
add()
函数负责将当前数与它的反向读取数相加,并更新到 c[] 数组中,同时处理进位情况和去除高位前导零。 -
pd()
函数判断当前数是否为回文数。 -
main()
函数:
输入进制数 n n n 和待处理的数(字符形式) c c c。
将字符转换为对应的数值存入 c [ ] c[] c[]。
初始化步数计数器 s t e p step step 为 0 0 0。
使用循环不断进行加法操作直至得到回文数或超过 30 30 30 步。
如果在 30 30 30 步以内得到了回文数,则输出STEP=
后跟最少步数;否则输出Impossible!
。
其他解析见代码注释。
AC代码如下
#include <bits/stdc++.h>
using namespace std;
const int S = 303; // 定义常量S,用于存储数字的缓冲区大小
int n, a[S], l; // n: 存储进制数,a[]: 辅助数组,l: 存储当前处理的数字长度
char c[S], d[S]; // c[]: 存储原始输入的字符数组,d[]: 临时存储反向读取的数字
void add() {// add() 函数:将原数字与其反向读取后的数字相加并更新至 c[]
for (int i = 0; i < l; i++) { // 将 d[] 中的内容逆序添加到 c[] 的末尾
d[l - i - 1] = c[i];
}
l += 2; // 增加总长度表示额外添加了反向读取的数字
for (int i = 0; i < l; i++) { // 进行高精度加法和处理进位
c[i] += d[i];
if (c[i] >= n) { // 若某位大于等于n,则向上一位进位
c[i + 1]++;
c[i] -= n;
}
}
while (!c[l - 1]) // 移除高位前导零
l--;
}
bool pd() { // pd() 函数:判断当前数字是否为回文数
for (int i = 0; i < l; i++) { // 检查从左到右与从右到左读取的每一位是否相同
if (c[i] != c[l - 1 - i]) {
return false;
}
}
return true; // 若是回文数,返回true
}
int main() {
cin >> n >> c; // 输入进制数 n 和待转换的字符串 c
l = strlen(c); // 计算字符串 c 的长度
for (int i = 0; i < l; i++) { // 将字符串中的字符转换为对应的数值
if (c[i] >= '0' && c[i] <= '9')
c[i] -= '0';
else
c[i] = c[i] - 'A' + 10; // 处理十六进制中字母 A-F 对应的数值
}
int step = 0; // 定义步数计数器
while (!pd()) { // 不断执行加法直到得到回文数或超过30步
step++;
if (step > 30)
break;
add();
}
if (step <= 30) // 根据步数输出结果
cout << "STEP=" << step;
else
cout << "Impossible!";
return 0;
}