题意:找第k小的回文串
思路:除去0的情况下,第一位有9个回文串,第二位有9个,第三位有90个,第四位有90个
我们可以枚举回文串的长度,对于长度为d的回文串,前(d+1)/2位是从10^((d+1)/2-1)到10^((d+1)/2)-1的。所以对于每一个长度的字符串我们都可以算出当前长度的回文串数量,我们枚举每一个长度,判断我们的n是否小于等于当前长度的回文串数量,如果大于,我们就更新n,继续找下一个长度,如果小于等于,就说明我们要找的回文串长度等于当前长度d。这时,我们的n就是当前长度回文串的第几个,拼接成一个长度为d的字符串就是我们的答案,这里注意一下,如果长度是奇数,我们需要减去中间的那个字符,例如字符串应为12321,我们直接拼会变为123321。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define int long long
ll qpow(ll a,ll p){
ll res=1;
while(p){
if(p&1) (res*=a);
(a*=a);
p>>=1;
}
return res;
}
signed main(){
int n;cin>>n;
if(n==1){
cout<<"0"<<endl;//特判一下,便于后面计算
return 0;
}
n--;
for(int d=1;;d++){//枚举回文串的长度
int x=(d+1)/2;//枚举有效位长度
if(n<=qpow(10,x-1)*9){
//n小于等于当前位数的回文串数量,说明n是d位的
string t=to_string(qpow(10,x-1)+n-1);
//看是当前位的第几个,因为是从0开始的,所以需要向前一个
string t1=t;//存前半部分的数字
reverse(t.begin(),t.end());//后半部分
t1+=t;//加起来就是整个第n个回文
if(d&1) t1.erase(x,1);//奇数的话会多加中间一位,删掉
cout<<t1<<endl;
break;
}
else{
n-=9*qpow(10,x-1);
//n大于当前位数的回文串数量说明位数不够
//继续看下一位
}
}
}