【SCOI2009】windy数
一看就知道是数位DP,但初学数位DP的第二题,还是不会。
设
f
[
i
]
[
j
]
f[i][j]
f[i][j]为前
i
i
i位中最高位是
j
j
j的
w
i
n
d
y
windy
windy数的个数。
显然,
f
[
i
]
[
j
]
=
s
u
m
(
f
[
i
−
1
]
[
k
]
)
f[i][j] = sum(f[i-1][k])
f[i][j]=sum(f[i−1][k]) 【
∣
k
−
j
∣
>
=
2
|k - j| >= 2
∣k−j∣>=2】
然后运用前缀和,把数拆开,一位一位地统计就 O K OK OK了。
#include<bits/stdc++.h>
using namespace std;
int f[12][12],a,b,num[12];
int ask(int x){
if(x==0)return 0;
int siz=0,ans=0;
while(x){
num[++siz]=x%10;
x/=10;
}
for(int i=1;i<=siz-1;i++)
for(int j=1;j<=9;j++)
ans+=f[i][j];//如果直接加 f[siz][0] 会受0下一位的数绝对值大于等于2的影响,所以循环一遍
for(int i=siz;i>0;i--){
if(i==siz){
for(int j=num[i]-1;j>=1;j--){
ans+=f[i][j];
}
continue;
}
for(int j=0;j<=num[i]-1;j++){
if(abs(j-num[i+1])<2)continue;
ans+=f[i][j];
}
if(abs(num[i+1]-num[i])<2)break;
if(i==1)ans++;
}
return ans;
}
int main(){
scanf("%d%d",&a,&b);
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)continue;
f[i][j]+=f[i-1][k];
}
printf("%d",ask(b)-ask(a-1));
return 0;
}