P2188 小Z的 k 紧凑数 题解
前置知识
解法
基础数位 DP,与 luogu P2657 [SCOI2009] windy 数 类似,记录当前位置、上一位填的数码,接着记忆化搜索即可。
需要注意的是有前导零时,此时不需要管相邻两位数字差的绝对值不超过 \(k\) 的限制。
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define sort stable_sort
#define endl '\n'
ll a[20],f[20][20];
ll divide(ll n,ll a[])
{
ll len=0;
while(n)
{
len++;
a[len]=n%10;
n/=10;
}
return len;
}
ll dfs(ll pos,ll pre,ll lead,ll limit,ll k)
{
if(pos<=0)
{
return 1;
}
if(f[pos][pre]!=-1&&lead==0&&limit==0)
{
return f[pos][pre];
}
ll ans=0,maxx=(limit==0)?9:a[pos],i;
for(i=0;i<=maxx;i++)
{
if(lead==1||abs(pre-i)<=k)
{
ans+=dfs(pos-1,i,(i==0)*lead,(i==maxx)*limit,k);
}
}
return (lead==0&&limit==0)?f[pos][pre]=ans:ans;
}
ll ask(ll n,ll k)
{
ll len=divide(n,a);
return dfs(len,0,1,1,k);
}
int main()
{
ll l,r,k;
cin>>l>>r>>k;
memset(f,-1,sizeof(f));
cout<<ask(r,k)-ask(l-1,k)<<endl;
return 0;
}
本文来自博客园,作者:hzoi_Shadow,原文链接:https://www.cnblogs.com/The-Shadow-Dragon/p/18301375,未经允许严禁转载。
版权声明:本作品采用 「署名-非商业性使用-相同方式共享 4.0 国际」许可协议(CC BY-NC-SA 4.0) 进行许可。