HDU 2089 不要62

HDU2089 不要62

题目描述:

杭州人称那些傻乎乎粘嗒嗒的人为62(音:laoer)。 
杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来,就可以消除个别的士司机和乘客的心理障碍,更安全地服务大众。 
不吉利的数字为所有含有4或62的号码。例如: 
62315 73418 88914 
都属于不吉利号码。但是,61152虽然含有6和2,但不是62连号,所以不属于不吉利数字之列。 
你的任务是,对于每次给出的一个牌照区间号,推断出交管局今次又要实际上给多少辆新的士车上牌照了。 

输入描述:

输入的都是整数对n、m(0<n≤m<1000000),如果遇到都是0的整数对,则输入结束。 

输出描述:

对于每个整数对,输出一个不含有不吉利数字的统计个数,该数值占一行位置。 

样例输入:

1 100
0 0

样例输出:

 

80

 

首先暴力...枚举每个数,log n枚举每一位判断是否符合,复杂度n log n,爆炸

正解~数位dp

求解区间l - r的答案,可以转换为求1 - r和1 - (l - 1)做差

那问题转换成了如何在区间1 - n中求解答案,问题就变得简单了

我们用dp[i][j]表示。一个长度为i的数字,最高位数字是j,有多少个符合条件的数

假设我们已经处理这个数字,考虑如何统计答案。

比如我们当前在统计第i位的答案,如果这个数字第i位是k,那么,第i位是[1 , i - 1]的其他数字一定都在范围内,直接统计

那么对于第i位等于k的数字?

第i位等于k的数字,并不是后面的位数可以随意了,后面的数字小于给定数字的范围。所以我们可以通过枚举

下一位的数字是什么,来统计当前位等于给定数字的数字。

 

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 
 6 #define RI register
 7 using namespace std;
 8 typedef long long ll;
 9 
10 #define max(a,b) ((a) > (b) ? (a) : (b))
11 #define min(a,b) ((a) < (b) ? (a) : (b))
12 
13 inline void read(int &x)
14 {
15     x = 0;
16     bool flag = 0;
17     char ch = getchar();
18     while(ch < '0' || ch > '9')
19     {
20         if(ch == '-')    flag = 1;
21         ch = getchar();
22     }
23     while(ch >= '0' && ch <= '9')
24     {
25         x = x * 10 + ch - '0';
26         ch = getchar();
27     }
28     if(flag)    x *= -1;
29 }
30 
31 int d[10],n,m; 
32 int dp[10][10];
33 
34 void init()
35 {
36     dp[0][0] = 1;
37     for(int i = 1;i <= 7;i ++)
38         for(int j = 0;j <= 9;j ++)
39             for(int k = 0;k <= 9;k ++)
40                 if(j != 4 && !(j == 6 && k == 2))
41                     dp[i][j] += dp[i - 1][k];
42 }
43 
44 int solve(int n)
45 {
46     int len = 0;
47     int ans = 0;
48     while(n)
49     {
50         d[++ len] = n % 10;
51         n /= 10;
52     }
53     d[len + 1] = 0;
54     for(int i = len; i >= 1;i --)
55     {
56         for(int j = 0; j < d[i];j ++)
57         {
58             if(d[i + 1] != 6 || j != 2)
59                 ans += dp[i][j];
60         }
61         if(d[i] == 4 || (d[i + 1] == 6 && d[i] == 2))
62             break;
63     }
64     return ans;
65 }
66  
67 int main()
68 {
69     init();
70     while(scanf("%d%d",&m,&n) == 2)
71     {
72         if(n == 0 && m == 0)    break;
73         printf("%d\n",solve(n + 1) - solve(m));
74     }
75     return 0;
76 }
View Code

 

posted @ 2017-10-22 18:49  illyaillyasviel  阅读(152)  评论(0编辑  收藏  举报