D - Palindromic Number 解説 by en_translator
To simplify casework, consider the following problem:
- What is the \(N\)-th smallest positive palindrome number?
(Solving this immediately solves the original problem.)
Let us enumerate the number of palindromes with a certain number of digits:
- \(1\)-digit palindrome numbers: \(1, 2, 3, \dots, 9\), there are \(9\) of them.
- \(2\)-digit palindrome numbers: \(11, 22, 33, \dots, 99\), there are \(9\) of them.
- \(3\)-digit palindrome numbers: \(111, 121, 131, \dots, 999\), there are \(90\) of them.
- \(4\)-digit palindrome numbers: \(1111, 1221, 1331, \dots, 9999\), there are \(90\) of them.
- \(\vdots\)
One can guess the pattern by staring at the enumerated palindrome numbers as follows:
- If \(d\) is odd, the most significant \((d+1)/2\) digits of the \(d\)-digit palindrome numbers comprises \(((d+1)/2)\)-digit positive integers.
- For example, the \(3\)-digit palindrome numbers have two significant digits as follows: \(11, 12, 13, \dots, 99\).
- If \(d\) is even, the most significant \(d/2\) digits of the \(d\)-digit palindrome numbers comprises \((d/2)\)-digit positive integers.
- For example, the \(5\)-digit palindrome numbers have two significant digits as follows: \(11, 12, 13, \dots, 99\).
Using this fact, it turns out that a \(d\)-digit palindrome number has the following properties:
- For \(x = \lfloor (d+1)/2 \rfloor\), the following two propositions hold:
- There are \(9 \times 10^{x-1}\) palindrome numbers with \(d\) digits.
- The \(x\) most significant digits of the \(k\)-th smallest palindrome number with \(d\) digits form an integer \(10^{x-1} + k - 1\)
By the observation above, one can obtain the \(N\)-th smallest palindrome numbers as follows.
- For \(d = 1, 2, \dots \), do the following.
- Let \(x = \lfloor (d + 1) / 2 \rfloor\).
- Check if \(N \leq 9 \times 10^{x - 1}\).
- If \(N \leq 9 \times 10^{x - 1}\), the sought palindrome number turns out to have \(d\) digits. Compute \(y = 10^{x-1} + N - 1\), and print the \(d\)-digit palindrome number staring with \(y\). Break the loop with respect to \(d\).
- Otherwise, the sough palindrome number has more than \(d\) digits. Subtract \(9 \times 10^{x-1}\) from \(N\).
The complexity is \(\mathrm{O}(\log N)\), which is fast enough. Note that the sought palindrome number can have as large as \(35\) digits, so avoid using a fixed-width integer type such as long long in C++ as it may cause an overflow. (Using a string type or a bigint helps circumventing the issue.)
Sample code (C++)
#include <iostream>
#include <string>
using namespace std;
long long TEN(int x) { return x == 0 ? 1 : TEN(x - 1) * 10; }
int main() {
long long N;
cin >> N;
if (N == 1) {
cout << 0 << endl;
return 0;
}
N--;
for (int d = 1;; d++) {
int x = (d + 1) / 2;
if (N <= 9 * TEN(x - 1)) {
string S = to_string(TEN(x - 1) + N - 1);
S.resize(d, ' ');
for (int i = x; i < d; i++) S[i] = S[d - 1 - i];
cout << S << endl;
return 0;
} else {
N -= 9 * TEN(x - 1);
}
}
}
投稿日時:
最終更新: