题解 P2188 小Z的 k 紧凑数

题目描述

小 Z 在草稿纸上列出了很多数,他觉得相邻两位数字差的绝对值不超过 \(k\) 的整数特别奇特,称其为 \(k\) 紧凑数。

现在小 Z 想知道 \([l,r]\) 内有多少个 \(k\) 紧凑数,希望你帮帮他。

具体思路

首先,要求数的个数,自然想到数位 dp。

然后可以用容斥原理拆询问。

\[ans=\sum_{i=l}^r calc(i)=\sum_{i=1}^r calc(i)-\sum_{i=1}^{l-1} calc(i) \]

由于只有一组询问,我们可以采用记忆化搜索的方式来解决本题。

要让相邻两位数字差的绝对值不超过 \(k\),我们只需要在每次搜索时记录上一位数字即可。

Code

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=20;
LL k,f[N][N],a[N];
LL dfs(int pos,int last,int lead,int limit){
	if(!pos)return 1;
	if(!limit&&!lead&&~f[pos][last])return f[pos][last];
	LL res=0,up=limit?a[pos]:9;
	for(int i=0;i<=up;i++){
		if(lead||abs(i-last)<=k){
			res+=dfs(pos-1,i,lead&&!i,limit&&i==up);
		}
	}
	if(!limit&&!lead)f[pos][last]=res;
	return res;
}
LL calc(LL x){
	int cnt=0;
	while(x){
		a[++cnt]=x%10;
		x/=10;
	}
	memset(f,-1,sizeof(f));
	return dfs(cnt,0,1,1);
}
int main(){
	LL l,r;scanf("%lld%lld%lld",&l,&r,&k);
	printf("%lld",calc(r)-calc(l-1));
	return 0;
} 
posted @ 2023-10-13 13:11  reclusive2007  阅读(30)  评论(0)    收藏  举报