裸的数位dp,但是要注意是否包含前导0的问题,然后每个数字看前一个数字是否可以转移即可。
AC代码:
#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
#define int long long
using namespace std;
inline char getc() {
static char buf[1000000],*p1=buf,*p2=buf;
return ((p1==p2)&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2))?EOF:*p1++;
}
template <class int_T> inline void read(int_T& x) {
x=0; char ch=getc(); for (;!(ch>='0'&&ch<='9');ch = getc());
for (;ch>='0'&&ch<='9';x=x*10+ch-'0',ch = getc());
}
int l,r,k,a[20],dp[20][200][10];
int dfs(int pos,int s,int pre,int lim,int head){
if(!pos) return 1;
if(!lim&&!head&&dp[pos][s][pre]!=-1) return dp[pos][s][pre];
int up=lim?a[pos]:9,res=0;
for(int i=0;i<=up;i++){
if(head||abs(i-pre)<=k) res+=dfs(pos-1,s+i,i,lim&&i==up,head&&i==0);
}
if(!head&&!lim) dp[pos][s][pre]=res;
return res;
}
int solve(int x){
int pos=0; memset(dp,-1,sizeof dp);
while(x) a[++pos]=x%10,x/=10;
return dfs(pos,0,0,1,1);
}
signed main(){
cin>>l>>r>>k;
cout<<solve(r)-solve(l-1);
return 0;
}