学习一发数位DP。
f[i][j]表示长度为i,最高位为j的windy数。
转移很简单,j为第i位,k为第i - 1位,如果j和k之差不小于2,那么有
f[i][j] += f[i - 1][k]
calc(int x)是计算[1, x - 1]内有多少windy数。
分三种算。
(1)长度比数x小。
(2)长度等于数x但是最高位比数x最高位小。
(3)其他的。
前两种很好计算,主要说(3)。
我们让枚举的高位逐渐与数x的高位相等,然后去枚举相邻位。
看代码。
#include <cstdio>
const int maxn = 15;
int f[maxn][maxn], A[maxn];
inline int __abs(int x) {
return x < 0 ? -x : x;
}
inline int calc(int x) {
int cnt = 0;
for(; x; x /= 10) A[++cnt] = x % 10;
int ans = 0;
for(int i = 1; i < cnt; i++) for(int j = 1; j < 10; j++)
ans += f[i][j];
for(int i = 1; i < A[cnt]; i++) ans += f[cnt][i];
for(int i = cnt; i >= 2; i--) {
for(int j = 0; j < A[i - 1]; j++) if(__abs(A[i] - j) >= 2)
ans += f[i - 1][j];
if(__abs(A[i] - A[i - 1]) <= 1) break;
}
return ans;
}
int main() {
for(int i = 0; i < 10; i++) f[1][i] = 1;
for(int i = 2; i <= 10; i++) for(int j = 0; j < 10; j++) for(int k = 0; k < 10; k++) if(__abs(j - k) >= 2)
f[i][j] += f[i - 1][k];
int a, b; scanf("%d%d", &a, &b);
printf("%d\n", calc(b + 1) - calc(a));
return 0;
}