Bzoj1026 windy数

Description

windy定义了一种windy数。不含前导零且相邻两个数字之差至少为2的正整数被称为windy数。 windy想知道,在A和B之间,包括A和B,总共有多少个windy数?

Input

包含两个整数,A B。

Output

一个整数。

Sample Input

【输入样例一】
1 10
【输入样例二】
25 50

Sample Output

【输出样例一】
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 }
原文地址:https://www.cnblogs.com/SilverNebula/p/5869074.html