提示
- 特定位数的回文数数量是可以快速计算出来的,对于特定的位数 \(n\),第一位由于不能有前导 \(0\),共有 \(9\) 种选择,而从第 \(2\) 位到第 \(\frac{n + 1}{2}\) 位都有 \(10\) 种选择(一个回文数完全由它的前半部分确定)。所以 \(n\) 位数中共有 \(S(n) = 9 * 10^\frac{n - 1}{2}\) 个回文数,特别的,\(S(1) = 10\)。
- 如何求 \(n\) 位数中第 \(k\) 小的回文数 \(X(k)\) ?首先 \(X(1)\) 一定是 \(100..001\) 这样的形式,所以第 \(k\) 小的我们直接从 \(X(1)\) 的第 \(\frac{n + 1}{2}\) 位开始,加上 \(k - 1\) 即可,注意最后还要再翻转一下。
实现
#include <bits/stdc++.h>
#define ll long long
using namespace std;
void solve() {
ll n; cin >> n;
if (n <= 10) {
cout << n - 1 << "\n";
return;
}
int len = 2;
ll t = 9;
n -= 10;
while (n - t > 0) {
n -= t;
if (len % 2 == 0) t *= 10;
len += 1;
}
int m = (len + 1) / 2;
ll x = 1;
for (int i = 0; i < m - 1; ++i) x *= 10; // 10 ^ (m - 1)
x += n - 1;
// 翻转,求后半部分,len 为奇数时需要忽略末位
string s = to_string(x);
if (len & 1) s.pop_back();
reverse(s.begin(), s.end());
cout << x << s << "\n";
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
solve();
return 0;
}