这是个裸的数位 d p dp dp吧。
求 A − > B A->B A−>B的就相当于求 ( 1 − > B ) − ( 1 − > ( A − 1 ) ) (1->B) - (1->(A-1)) (1−>B)−(1−>(A−1))
d p [ i ] [ j ] dp[i][j] dp[i][j]表示 枚举到第 i i i位(从高位到底为枚举,这样更有利于处理上限),前一位是 j j j的方案数、
d p [ i ] [ j ] − > d p [ i + 1 ] [ ] j 0 ] dp[i][j]->dp[i+1][]j_0] dp[i][j]−>dp[i+1][]j0] 要求 j j j可以转化成为 j 0 j_0 j0
同时我们要记录两个参数: S X SX SX(上限),当突破上限时 b r e a k break break
Q D L QDL QDL前导零,相当于记录位数
直接记忆化搜索就可以了
#include <bits/stdc++.h>
using namespace std ;
#define clr(a) memset((a),0,sizeof((a)))
typedef long long ll ;
ll a,b ;
ll dp[20][10]; //dp[i][j]表示前i位,前一位为j
int dig[20] ;
ll DP(int k,int last,int SX,int QDL){
if (k==0) return 1 ;
if (!QDL && !SX && dp[k][last]!=-1) return dp[k][last];
int ans=0 ;
for (int i=0;i<=9;i++){
if (SX && i>dig[k]) break ;
if (abs(i-last)<2) continue ;
int t=i ;
if (QDL && !i) t=-10;
ans+=DP(k-1,t,(SX && i==dig[k]),(t==-10)) ;
}
if (!SX && !QDL) dp[k][last]=ans ;
return ans ;
}
ll solve(ll x){
int dsum=0;
clr(dig) ;
memset(dp,-1,sizeof(dp)) ;
while(x){
dig[++dsum]=x%10 ;
x/=10;
}
return DP(dsum,-10,1,1) ;
}
int main(){
scanf("%lld%lld",&a,&b) ;
ll ans=solve(b)-solve(a-1) ;
printf("%lld\n",ans) ;
}