题目大意:
w
i
n
d
y
windy
windy定义了一种
w
i
n
d
y
windy
windy数。不含前导零且相邻两个数字之差至少为
2
2
2的正整数被称为
w
i
n
d
y
windy
windy数。
windy想知道,在
A
A
A和
B
B
B之间,包括
A
A
A和
B
B
B,总共有多少个
w
i
n
d
y
windy
windy数?
1
<
=
A
<
=
B
<
=
2000000000
1 <= A <= B <= 2000000000
1<=A<=B<=2000000000
分析:
数位
d
p
dp
dp,
设
d
p
i
,
j
dp_{i,j}
dpi,j表示选到了第
i
i
i位,第
i
i
i位选的数是
j
j
j时的
w
i
n
d
y
windy
windy数总数。
不难发现
d
p
i
,
j
=
∑
k
=
0
9
d
p
i
−
1
,
k
(
a
b
s
(
j
−
k
)
≥
2
)
dp_{i,j}=\sum_{k=0}^{9}dp_{i-1,k}(abs(j-k)≥2)
dpi,j=∑k=09dpi−1,k(abs(j−k)≥2)
然后我们可以发现,对于
询问的区间
[
A
,
B
]
[A,B]
[A,B]内的
w
i
n
d
y
windy
windy数总数,
可以拆成区间
[
1
,
B
]
[1,B]
[1,B]的
w
i
n
d
y
windy
windy数总数
−
-
−区间
[
1
,
A
−
1
]
[1,A-1]
[1,A−1]的
w
i
n
d
y
windy
windy总数
即
S
u
m
[
A
,
B
]
=
S
u
m
[
1
,
B
]
−
S
u
m
[
1
,
A
−
1
]
Sum_{[A,B]}=Sum_{[1,B]}-Sum_{[1,A-1]}
Sum[A,B]=Sum[1,B]−Sum[1,A−1]
然后我们现在就是要求对于一个数
x
x
x,
在
[
1
,
x
]
[1,x]
[1,x]内有多少个
w
i
n
d
y
windy
windy数,
我们将
x
x
x十进制下的每一位拆出来,设位数为
l
e
n
len
len,
那么我们分类讨论一下,
①对于最高的前
i
i
i位,都填上
x
x
x的前
i
i
i位时的
w
i
n
d
y
windy
windy数个数
②位数小于
l
e
n
len
len的数的
w
i
n
d
y
windy
windy数个数
③位数为
l
e
n
len
len,最高位的数填上
<
x
<x
<x的最高位的能填的数时的
w
i
n
d
y
windy
windy个数
④它本身是否是个
w
i
n
d
y
windy
windy数
代码:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <queue>
#include <cstdlib>
#include <algorithm>
using namespace std;
int dp[20][10], Wxy[20], A, B, cnt, Total;
void Pre_Work()
{
for (int i = 0; i <= 9; i++) dp[1][i] = 1;
for (int i = 2; i <= 10; i++)
for (int j = 0; j <= 9; j++)
for (int k = 0; k <= 9; k++)
if (abs(j - k) >= 2) dp[i][j] = dp[i][j] + dp[i - 1][k];
}
int Work(int x)
{
cnt = 0, Total = 0;
for (; x; x /= 10) Wxy[++cnt] = x % 10;
for (int i = cnt - 1; i >= 0; i--)
{
if (i == 0) { ++Total; break; }
for (int j = 0; j < Wxy[i]; j++)
if (abs(j - Wxy[i + 1]) >= 2) Total += dp[i][j];
if (abs(Wxy[i] - Wxy[i + 1]) < 2) break;
}
for (int i = 1; i < Wxy[cnt]; i++) Total += dp[cnt][i];
for (int i = 1; i < cnt; i++)
for (int j = 1; j <= 9; j++) Total += dp[i][j];
return Total;
}
int main()
{
Pre_Work();
scanf("%d %d", &A, &B);
printf("%d\n", Work(B) - Work(A - 1));
return 0;
}