题意
所有相邻位数差距大于等于二的数称为 w i n d y windy windy数,问 l ∼ r l\sim r l∼r有多少个 w i n d y windy windy数。
解题方法
这个题是数位
d
p
dp
dp的板子题。我们关注的相邻的两位数是否差的绝对值是否大于等于2,我们就可以关注位数来解决这个题,我们定义一个二维数组
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]表示前
i
i
i 位首位数是
j
j
j 中有多少个
w
i
n
d
y
windy
windy 数,那么转移方程式就是如下了:
d
p
[
i
]
[
j
]
=
∑
k
=
0
&
&
a
b
s
(
j
−
s
)
≥
2
9
d
p
[
i
−
1
]
[
k
]
dp[i][j]=\sum_{k=0\&\&abs(j-s)\geq2}^{9}dp[i-1][k]
dp[i][j]=k=0&&abs(j−s)≥2∑9dp[i−1][k]
然后在统计
w
i
n
d
y
windy
windy数的时候我们需要一个小技巧,就是我们看能不能向下查询的时候下一位满不满足,如果不满足就break,结束查询。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
long long dp[15][15];
long long l,r;
long long a[15];
long long work(long long x)
{
memset(a,0,sizeof(a));
long long weishu=0;
while(x)
{
weishu++;
a[weishu]=x%10;
x/=10;
}
long long ans=0;
for(long long i=1;i<weishu;i++)
for(long long j=1;j<=9;j++)
ans+=dp[i][j];
for(long long i=1;i<a[weishu];i++)
ans+=dp[weishu][i];
for(long long i=weishu-1;i;i--)
{
for(long long j=0;j<a[i];j++)
if(abs(a[i+1]-j)>=2)
ans+=dp[i][j];
if(abs(a[i+1]-a[i])<=2)break;
}
return ans;
}
int main()
{
scanf("%lld%lld",&l,&r);
for(long long i=0;i<=9;i++)
dp[1][i]=1;
for(long long i=2;i<=12;i++)
for(long long j=0;j<=9;j++)
{
for(long long k=0;k<=9;k++)
if(abs(k-j)>=2)
dp[i][j]+=dp[i-1][k];
}
cout<<work(r+1)-work(l)<<'\n';
return 0;
}