https://www.luogu.com.cn/blog/virus2017/shuweidp
https://www.luogu.com.cn/problem/P2657
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define ll long long
const int maxn = 200100;
ll dp[20][10]; //dp[i][j]为当前在 i 位,前一位的数是 j 时的方案数。
ll num[20];
ll dfs(int n,bool lead,bool limit,int pre) //当前位 前导0标记 位限制 前一位数
{
if(n<0) return 1;
if(!limit && !lead && dp[n][pre]!=-1) return dp[n][pre];
ll ans=0;
int up=limit?num[n]:9;
for(int i=0;i<=up;i++)
{
if(!lead &&abs(pre-i)<2) continue; //无前导0,并且相邻两数小于2 直接遍历下一个
ans+=dfs(n-1,lead&&i==0,limit&&i==up,i); //有前导0标记并且当前遍历位为0,前导0传递下去
} //有限制标志并且当前遍历位到了最大值,传递限制
if(!limit&&!lead) dp[n][pre]=ans; //无限制,记忆化
return ans;
}
ll solve(ll n)
{
int len=0;
while(n)
{
num[len++]=n%10;
n/=10;
}
return dfs(len-1,1,1,0);
}
int main()
{
ll a,b;
memset(dp,-1,sizeof(dp));
while(scanf("%lld%lld",&a,&b)!=EOF)
{
printf("%lld
",solve(b)-solve(a-1));
}
return 0;
}