「AtCoder ABC161D」Lunlun Number

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;
}

猜你喜欢

转载自www.cnblogs.com/-Wallace-/p/12634816.html