数位dp模板题。
$dp[t][p]$表示还剩$t$位,上一位填的是$p$的方案数。
那么转移就是$dp[t][p] = \sum dp[t-1][q], abs(p-q) \geq 2$.
这里采用dls的可读性极高的写法。
举个例子,如果我们要计算$[1,3323]$的答案,那么先把$[1,999]$的答案整段算完。
然后剩下的一位一位卡着算就行了。
具体见代码,如果实在不懂可以画图理解。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69/**
* @Author: Mingyu Li
* @Date: 2019-03-10T09:32:31+08:00
* @Email: class11limingyu@126.com
* @Filename: [SCOI2009]windy数.cpp
* @Last modified by: Mingyu Li
* @Last modified time: 2019-03-10T10:19:58+08:00
*/
#include <bits/stdc++.h>
#define tpname typename
#define Go(i , x , y) for(register int i = x; i <= y; i++)
#define God(i , y , x) for(register int i = y; i >= x; i--)
typedef long long LL;
typedef long double ld;
typedef unsigned long long ULL;
template < tpname T > void sc(T& t) {
char c = getchar(); T x = 1; t = 0; while(!isdigit(c)) {if(c == '-') x = -1; c = getchar();}
while(isdigit(c)) t = t * 10 + c - '0' , c = getchar();t *= x;
}
template < tpname T , tpname... Args > void sc(T& t , Args&... args) {sc(t); sc(args...);}
template < tpname T > T mul(T x , T y , T _) {
x %= _,y %= _; return ((x * y - (T)(((ld)x * y + 0.5) / _) * _) % _ + _) % _;
}
int d[20] , l , r;
int dp[20][20];
int F(int k , int p) {
if(dp[k][p] != -1) return dp[k][p];
if(k == 0) return dp[k][p] = 1;
int ans = 0;
Go(q , 0 , 9) {
if(abs(p - q) >= 2) ans += F(k-1 , q);
}
return dp[k][p] = ans;
}
int cal(int x) {
int m = 0;
while(x) {
d[m] = x%10; x /= 10; m++;
}
int ans = 0;
God(i , m-1 , 1) {
Go(j , 1 , 9) ans += F(i-1 , j); // 整段
}
int pre = -100;
God(i , m-1 , 0) {
Go(j , (i == m-1) ? 1 : 0 , d[i] - 1) { // 卡着边界
if(abs(pre - j) >= 2) ans += F(i , j);
}
if(abs(pre - d[i]) < 2) break;
pre = d[i];
// 钦定一位之后继续
}
return ans;
}
int main() {
memset(dp , -1 , sizeof(dp));
std::cin >> l >> r;
// cal 计算的是开区间
std::cout << cal(r+1) - cal(l) << std::endl;
return 0;
}