Bzoj1026 windy数
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
【数据规模和约定】
20%的数据,满足 1 <= A <= B <= 1000000 。
100%的数据,满足 1 <= A <= B <= 2000000000 。
9
【输出样例二】
20
【数据规模和约定】
20%的数据,满足 1 <= A <= B <= 1000000 。
100%的数据,满足 1 <= A <= B <= 2000000000 。
对Windy这个词感到异常亲切
数位DP
先预处理出f[数的位数i][首位是j]=满足条件的windy数的个数。
读入范围时,先累加位数小于n的位数的答案数,然后特殊处理位数等于n的位数的答案。
1 /*by SilverN*/ 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 using namespace std; 8 const int mxn=15; 9 int p[mxn]; 10 int f[mxn][mxn]; 11 int L,R; 12 void init(){ 13 int i,j; 14 p[1]=1; 15 for(i=2;i<=10;i++)p[i]=p[i-1]*10; 16 for(i=0;i<=9;i++)f[1][i]=1; 17 for(i=2;i<=10;i++) 18 for(j=0;j<=9;j++) 19 for(int k=0;k<=9;k++) 20 if(abs(j-k)>=2)f[i][j]+=f[i-1][k]; 21 return; 22 } 23 int calc(int n){ 24 if(!n)return 0; 25 int res=0; 26 int len=10;while(p[len]>n)len--; 27 int i,j; 28 for(i=1;i<len;i++) 29 for(j=1;j<=9;j++)res+=f[i][j];//累加位数小于n的答案数 30 j=n/p[len]; 31 for(i=1;i<j;i++)res+=f[len][i];//累加位数等于n而最高位小于n的答案数 32 int last=j; 33 n%=p[len]; 34 for(i=len-1;i;i--){ 35 int tmp=n/p[i]; 36 for(j=0;j<=tmp;j++){ 37 if(i!=1 && j==tmp)continue; 38 if(abs(last-j)>=2)res+=f[i][j]; 39 } 40 if(abs(tmp-last)<2)break; 41 last=tmp; 42 n%=p[i]; 43 } 44 return res; 45 } 46 int main(){ 47 init(); 48 scanf("%d%d",&L,&R); 49 printf("%d",calc(R)-calc(L-1)); 50 return 0; 51 }
本文为博主原创文章,转载请注明出处。