200字
Luogu P1015 [NOIP 1999 普及组] 回文数
2025-10-02
2025-10-02

思路

  1. 问题分析:给定一个 N 进制数 M(字符串形式,最多 100 位),通过不断将其与它的反转数进行 N 进制加法,直到得到回文数。如果在 30 步内得到回文数,输出步数;否则输出 "Impossible!"。

  2. 关键步骤

    • 判断回文:检查字符串是否从左到右和从右到左读相同。

    • 字符串反转:获取当前字符串的反转形式。

    • N 进制加法:模拟加法过程,处理进位和进制转换(注意 16 进制时使用大写字母)。

  3. 算法流程

    • 检查初始数是否回文,若是则输出 0 步。

    • 循环最多 30 步:

      • 将当前数与其反转进行 N 进制加法。

      • 检查结果是否回文,若是则输出当前步数。

    • 若 30 步内未得到回文数,输出 "Impossible!"。

代码

#include <iostream>
#include <string>
#include <algorithm>
#include <cctype>
using namespace std;

// 字符转数字(支持小写和大写字母)
int charToDigit(char c) {
    if (c >= '0' && c <= '9')
        return c - '0';
    else if (c >= 'A' && c <= 'F')
        return c - 'A' + 10;
    else if (c >= 'a' && c <= 'f')
        return c - 'a' + 10;
    else
        return -1; // 无效字符
}

// 数字转字符(输出大写字母)
char digitToChar(int num) {
    if (num < 10)
        return '0' + num;
    else
        return 'A' + num - 10;
}

// 判断字符串是否为回文
bool isPalindrome(string s) {
    int n = s.size();
    for (int i = 0; i < n / 2; i++) {
        if (s[i] != s[n - 1 - i])
            return false;
    }
    return true;
}

// 反转字符串
string reverseString(string s) {
    string t = s;
    reverse(t.begin(), t.end());
    return t;
}

// N进制加法(两个字符串长度必须相同)
string add(string a, string b, int base) {
    int len = a.size();
    string result = "";
    int carry = 0;
    for (int i = len - 1; i >= 0; i--) {
        int num1 = charToDigit(a[i]);
        int num2 = charToDigit(b[i]);
        int sum = num1 + num2 + carry;
        carry = sum / base;
        int digit = sum % base;
        result.push_back(digitToChar(digit));
    }
    if (carry > 0) {
        result.push_back(digitToChar(carry));
    }
    reverse(result.begin(), result.end());
    return result;
}

int main() {
    int N;
    string M;
    cin >> N >> M;

    // 检查初始数是否回文
    if (isPalindrome(M)) {
        cout << "STEP=0" << endl;
        return 0;
    }

    string current = M;
    int step = 0;
    while (step < 30) {
        step++;
        string rev = reverseString(current);
        current = add(current, rev, N);
        if (isPalindrome(current)) {
            cout << "STEP=" << step << endl;
            return 0;
        }
    }

    cout << "Impossible!" << endl;
    return 0;
}

评论