1.先用数位dp求出小于x的回文有多少个
2.再加上k,就是求刚好有这么多个回文的数是多少
3.二分答案
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<cmath>
using namespace std;
typedef long long ll;
ll x, k, f[20], p[15];
void init() {
p[0] = 1;
for (int i = 1; i < 15; i++)p[i] = 10ll * p[i - 1];
for (int i = 2; i < 20; i++)f[i] = 9ll * p[i - 1 >> 1];
f[1] = 10;
}
ll dp(ll x) {
if (x >= 0 && x <= 9)return x + 1;// 把0也算上了
ll res = 0;
vector<int> v;
while (x) {
v.push_back(x % 10);
x /= 10;
}
int n = v.size();
ll a = 0, b = 0;
for (int i = n - 1; i >= n >> 1; i--) {//求正好位数是n的回文数
int x = v[i];
res += p[i - n / 2] * (x - 1);//第一位不能为0
if (i != n - 1)res += p[i - n / 2];
}
// 判断后半段是不是比前半段大,如果大,那么还有一个回文
for (int i = n / 2 - 1; i >= 0; i--)
b = b * 10 + v[i];
for (int i = n + 1 >> 1; i < n; i++)
a = a * 10 + v[i];
if (b >= a)res++;
// 加上1~n-1位数的回文数
for (int i = 1; i < n; i++)
res += f[i];
return res;
}
int main() {
init();
cin >> x >> k;
ll y = dp(x - 1) + k;//先求出小于x的回文数
ll l = 1, r = 1e18;
while (l < r) {
ll mid = l + r >> 1;
if (dp(mid) >= y)r = mid;
else l = mid + 1;
}
cout << l << endl;
return 0;
}
京公网安备 11010502036488号