数位dp入门题,dfs(len,ps,lead,up)表示当前枚举到第len位,前一位数为ps,是否有前导0,是否达到上界。
数位dp这一篇讲得很好orz
#include<cstdio>
#include<cstring>
#include<iostream>
#define max(x,y) ((x)>(y) ? (x) : (y))
#define min(x,y) ((x)<(y) ? (x) : (y))
#define LL long long
using namespace std;
inline LL getll() {
char ch;
LL p=0,t;
for(ch=getchar();ch!='-' && !(ch>='0' && ch<='9');ch=getchar());
if(ch=='-') t=-1,ch=getchar();
else t=1;
for(;ch>='0' && ch<='9';ch=getchar()) {
p=p*10+ch-48;
}
return t*p;
}
int dig[25];
LL d[25][2525];
LL dfs(int len,int ps,bool lead,bool up) {
if(len==0) {
return 1;
}
if(!up && !lead && d[len][ps]!=-1)//只有在无前导0且小于上界的情况下才记录
return d[len][ps];
int limit=up ? dig[len] : 9;
LL ret=0;
for(int i=0;i<=limit;i++) {
if(!lead && i>=ps-1 && i<=ps+1) continue; //不合法
ret+=dfs(len-1,i,lead&&i==0,up&&i==limit);
}
if(!up && !lead)
d[len][ps]=ret;//只有在无前导0且小于上界的情况下才记录
return ret;
}
LL cal(LL num) {
int len=0;
while(num) {
dig[++len]=num%10;
num/=10;
}
return dfs(len,0,true,true);
}
int main()
{
LL a,b;
memset(d,-1,sizeof d);
a=getll();
b=getll();
cout<<cal(b)-cal(a-1)<<endl;
return 0;
}