原题地址:https://www.lydsy.com/JudgeOnline/problem.php?id=1026
思路:这题要求不能有前导0,所以需要再加一维lead来控制前导0
记录一下我现在对于前导0的一些理解。
在dfs中,limit就是判断你当前这位数是否受到了遍历的上下界的影响,lead就是判断你当前这位数字前面是否有前导0(即前面是否全是0).那么在这道题中,很明显,如果你一位数前面没有前导0并且与它的差值 <1 < 1 <script type="math/tex" id="MathJax-Element-210"><1</script>,那么这就是不符合状态的,需要continue。如果你与前面的差值同样是 <1 < 1 <script type="math/tex" id="MathJax-Element-211"><1</script>但是你有前导0(其实也可以理解为你当前这位数是位数最高的),比如说0100,第一位0其实是不存在的,只是为了方便统一形式,所以将前面一位数视为0.那么前面的01其实是合法的,因为1是最高位,他不能与前面的进行比较。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 4;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
int n, m, cnt;
int dp[100][10];//dp[i][j]表示处理第i位,前一位是数字j
//也可以开三维dp
int a[100];
int dfs(int pos, int pre, bool limit, bool lead) {
if(pos == -1) return 1;
if(!limit && !lead && dp[pos][pre] != -1) return dp[pos][pre]; //lead 主要是在这里起作用
int up = limit ? a[pos] : 9;
int ans = 0;
for(int i = 0; i <= up; i++) {//与下面的写法其实是一样的
if(!lead && abs(i - pre) < 2) continue;
ans += dfs(pos - 1, i, limit && i == up, lead && i == 0);
// if(lead) {
// for(int i = 0; i <= up; i++) {
// ans += dfs(pos - 1, i, limit && i == up, lead && i == 0);
// }
// } else {
// for(int i = 0; i <= up; i++) {
// if(abs(pre - i) >= 2) ans += dfs(pos - 1, i, limit && i == up, 0);
// }
// }
if(!limit && !lead ) dp[pos][pre] = ans; //lead 主要是在这里起作用
return ans;
}
int solve(int x) {
cnt = 0;
while(x) {
a[cnt++] = x % 10;
x /= 10;
}
return dfs(cnt - 1, -1, true, true);
}
int main() {
memset(dp, -1, sizeof(dp));
while(~scanf("%d%d", &n, &m)) {
printf("%d\n", solve(m) - solve(n - 1));
}
return 0;
}