题目描述
w i n d y windy windy定义了一种 w i n d y windy windy数。不含前导零且相邻两个数字之差至少为 2 2 2的正整数被称为 w i n d y windy windy数。 w i n d y windy windy想知道,在 A A A和 B B B之间,包括 A A A和 B B B,总共有多少个 w i n d y windy windy数?
输入格式
包含两个整数, A A A, B B B。
输出格式
一个整数
S a m p l e Sample Sample I n p u t Input Input
【输入样例一】
1 1 1 10 10 10
【输入样例二】
25 25 25 50 50 50
S a m p l e Sample Sample O u t p u t Output Output
【输出样例一】
9 9 9
【输出样例二】
20 20 20
数据范围与提示
100 100 100%的数据,满足 1 ≤ A ≤ B ≤ 2000000000 1 ≤ A ≤ B ≤ 2000000000 1≤A≤B≤2000000000 。
传说中数位 D P DP DP有 2 2 2种写法,但是本蒟蒻只会一种。。。
f
[
i
]
[
j
]
f[i][j]
f[i][j]表示后
i
i
i位,第
i
i
i位为j的windy数的个数
f
[
i
]
[
j
]
=
Σ
f
[
i
−
1
]
[
k
]
f[i][j] = Σf[i - 1][k]
f[i][j]=Σf[i−1][k](
∣
j
−
k
∣
|j - k|
∣j−k∣
>
=
2
)
>= 2)
>=2)
然后我们就可以去求解答案了
运用前缀和思想
l
l
l~
r
r
r中的
w
i
n
d
y
windy
windy数个数
=
=
=
(
(
(
1
1
1 ~
r
r
r中windy数个数)
−
-
− (
1
1
1 ~
l
−
1
l - 1
l−1中
w
i
n
d
y
windy
windy数
)
)
)的个数
然后,我们就可以去统计答案了
假设将一个数x分解到数位
a
[
1
]
,
a
[
2
]
,
…
,
a
[
l
e
n
]
a[1] , a[2] , … , a[len]
a[1],a[2],…,a[len]
则
- 位数 < l e n <len <len的数一定都是范围内的
- 位数 = l e n =len =len,首位 < a [ 1 ] <a[1] <a[1]的也一定是范围内的
- 位数 = l e n =len =len,首位 = a [ 1 ] =a[1] =a[1]的贴近上界部分直接从高位到低位枚举每一位的取值,若该位上的值与前 1 1 1位相差至少为 2 2 2则可以统计答案,若该位已经与前一位的值相差 < 2 <2 <2则可直接跳出循环。
代码
#include<stdio.h>
#include<cstring>
using namespace std;
const int maxn = 15;
int a[maxn];
int f[maxn][10];
int abs(int x){return x > 0 ? x : -x;}
void dp()
{
// f[i][j]表示后i位,且第i位为j的windy数个数
// f[i][j] = Σf[i - 1][k](abs(j - k) >= 2)
// f[0][0] = 1
for(int i = 0;i <= 9;i++) f[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) f[i][j] += f[i - 1][k];
}
int solve(int x)//1~(x-1)中windy数的个数
{
int len = 0;
for(;x;a[++len] = x % 10 , x /= 10);
int res = 0;
for(int i = 1;i < len;i++)
for(int j = 1;j <= 9;j++) res += f[i][j];
for(int i = 1;i < a[len];i++) res += f[len][i];
for(int i = len - 1;i >= 1;i--)
{
for(int j = 0;j < a[i];j++)
if(abs(j - a[i + 1]) >= 2) res += f[i][j];
if(abs(a[i + 1] - a[i]) < 2) break;
}
return res;
}
int main()
{
dp();
int l , r;
scanf("%d%d",&l,&r);
printf("%d\n",solve(r + 1) - solve(l));
return 0;
}