【BZOJ1026】【SCOI2009】windy数
Description
windy定义了一种windy数。不含前导零且相邻两个数字之差至少为2的正整数被称为windy数。 windy想知道,在A和B之间,包括A和B,总共有多少个windy数?
Input
包含两个整数,A B。
Output
一个整数。
Sample Input1
1 10
Sample Output1
9
Sample Input2
25 50
Sample Output2
20
Hint
100%的数据,满足$ 1\leq A \leq B \leq 2*10^{9}$ 。
Solution
数位DP,用\(f_{i,j}\)表示i位数,最高位为j的情况,容易得出DP方程为\(f_{i,j}=\Sigma_{k} f_{i-1,k} (|k-j| \leq 2)\).
Code
#include <stdio.h>
#define MN 15
#define R register
int a,b,f[MN][MN],q[MN];
void init(){
for (R int i=0; i<10; ++i) f[1][i]=1;
for (R int i=2; i<11; ++i)
for (R int j=0; j<10; ++j)
for (R int k=0; k<10; ++k)
if (j-k>1||k-j>1)
f[i][j]+=f[i-1][k];
}
int get(int x){
if (!x) return 0;R int res=0,k=0;
while(x){q[++k]=x%10;x/=10;}
for (R int i=1; i<k; ++i)
for (R int j=1; j<10; ++j)
res+=f[i][j];
for (R int i=1; i<q[k]; ++i)
res+=f[k][i];
for (R int i=k-1; i; --i){
for (R int j=0; j<q[i]; ++j)
if (j-q[i+1]>1||q[i+1]-j>1)
res+=f[i][j];
if (q[i+1]-q[i]>1||q[i]-q[i+1]>1){
if (i==1) ++res;
continue;
}break;
}return res;
}
int main(){
init();scanf("%d %d",&a,&b);
printf("%d",get(b)-get(a-1));
return 0;
}