Description
我们称正整数 \(X\) 为 lunlun number
,当且仅当 \(X\) 满足:
- 在 \(X\) 的十进制表示(无前导零)中,任意两个相邻的数位的数值之差的绝对值 \(\le 1\) 。
如:\(1234,1,334,\text{etc.}\);
不是 lunlun number 的例子:\(31415,119,13579,\text{etc.}\)
现给定 \(K\) ,求出所有 lunlun number 中第 \(K\) 小的。
Hint
\(1\le K\le 10^5\)
Solution
数位dp固然可做,但这里提供一种更为简便的方法。
一个简单的思路是 预处理打表。
什么意思呢?就是将那个什么 lunlun number 全部预先计算出来,然后排序,最后取第 \(K\) 个即可。
预处理可以使用类似于 Bfs 的方法实现。如果当前出队的数大于某个较大值时停止。实测“较大值”取 \(10^{11}\) 时,共可以得到 \(3\times 10^5\) 个数以上,根据 \(K\) 的数据范围,可以符合要求。
Code
#include<iostream>
#include<algorithm>
#include<climits>
#include<cmath>
#include<vector>
#include<queue>
using namespace std;
vector<long long> num;
long long Q[int(1e7)];
int l=1,r=0;
inline void prepare() {
for(register int i=1;i<10;i++)
Q[++r]=i;
while(r>l) {
long long cur=Q[l++];
if(cur>1e11) return;
num.push_back(cur);
int back=cur%10;
Q[++r]=cur*10ll+back;
if(back!=0) Q[++r]=cur*10ll+back-1;
if(back!=9) Q[++r]=cur*10ll+back+1;
}
}
signed main() {
prepare();
int k;
cin>>k;
sort(num.begin(),num.end()) ;
cout<<num[k-1]<<endl;
}