Description
windy定义了一种windy数。不含前导零且相邻两个数字之差至少为2的正整数被称为windy数。 windy想知道,
在A和B之间,包括A和B,总共有多少个windy数?
Input
包含两个整数,A B。
Output
一个整数
Sample Input
【输入样例一】
1 10
【输入样例二】
25 50
1 10
【输入样例二】
25 50
Sample Output
【输出样例一】
9
【输出样例二】
20
9
【输出样例二】
20
HINT
【数据规模和约定】
100%的数据,满足 1 <= A <= B <= 2000000000 。
数位DP,令f[i][j]为i位数,开头为j的windy数的个数,方程f[i][k]=∑f[i-1][j](abs(k-j)>=2)
#include <cstdio>
#include <cstring>
using namespace std;
int base[20];
int num[20][20];
inline int abs(int x){
return x<0?-x:x;
}
inline void dp(){
base[1]=1;
for(int i=2;i<=10;i++)
base[i]=base[i-1]*10;
for(int i=0;i<=9;i++)
num[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(k-j)>=2)
num[i][k]+=num[i-1][j];
}
inline int get(int x){
if(!x)
return 0;
int cnt=10;
while(base[cnt]>x)
cnt--;
int ans=0;
int t=x/base[cnt];
for(int i=1;i<t;i++)
ans+=num[cnt][i];
for(int i=1;i<cnt;i++)
for(int j=1;j<=9;j++)
ans+=num[i][j];
int pre=t;
x%=base[cnt];
cnt--;
for(int i=cnt;i>=1;i--){
t=x/base[i];
if(i!=1){
for(int j=0;j<t;j++)
if(abs(j-pre)>=2)
ans+=num[i][j];
}
else for(int j=0;j<=t;j++)
if(abs(j-pre)>=2)
ans+=num[i][j];
if(abs(t-pre)<2)
break;
pre=t;
x%=base[i];
}
return ans;
}
int main(){
//freopen("a.in","r",stdin);
//freopen("a.out","w",stdout);
int l,r;
scanf("%d %d",&l,&r);
dp();
int v=get(l-1);
printf("%d\n",get(r)-get(l-1));
return 0;
}