hdu 2089 不要62

传送门

不要62

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 30264    Accepted Submission(s): 10657


Problem Description
杭州人称那些傻乎乎粘嗒嗒的人为62(音:laoer)。
杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来,就可以消除个别的士司机和乘客的心理障碍,更安全地服务大众。
不吉利的数字为所有含有4或62的号码。例如:
62315 73418 88914
都属于不吉利号码。但是,61152虽然含有6和2,但不是62连号,所以不属于不吉利数字之列。
你的任务是,对于每次给出的一个牌照区间号,推断出交管局今次又要实际上给多少辆新的士车上牌照了。
 
Input
输入的都是整数对n、m(0<n≤m<1000000),如果遇到都是0的整数对,则输入结束。
 
Output
对于每个整数对,输出一个不含有不吉利数字的统计个数,该数值占一行位置。
 
Sample Input
1 100 0 0
 
Sample Output
80
 
Author
qianneng
 
Source
 
Recommend
lcy   |   We have carefully selected several similar problems for you:  2094 2090 2091 2093 2092 

题解:

转自:http://blog.csdn.net/wangyuquanliuli/article/details/13761661

数位dp适合在一段数的区间内找出满足某些条件的数的个数,这个时候往往不能之间遍历,肯定会超时,则一般使用数位dp来解决

数位dp的常见形式是dp[i][j],表示开头是j的i位数满足条件的有多少个,当然也有其他dp[i][j][k]等等,但i,j,k都很小,不会像直接遍历那么耗时

像这道题的话,知道了dp[i][j]表示的是啥,就能列出状态转移方程(稍微认真看就能理解的):

注意:

一开始也想到了数位dp,但是感觉太烦没想做,后来想想,只要从高位往低位累加dp的值就好了

转移方程:

 1 for(int i=1;i<=7;i++)
 2     {
 3         for(int j=0;j<10;j++)//枚举第i位可能出现的数
 4         {
 5             for(int k=0;k<10;k++)//枚举第i-1位可能出现的数
 6             {
 7                 if(j!=4&&!(j==6&&k==2))
 8                     dp[i][j]  += dp[i-1][k];
 9             }
10         }
11     }
16562586 2016-03-15 17:40:14 Accepted 2089 0MS 1564K 1502 B G++ czy

我的代码:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <map>
 4 #include <cstring>
 5 #include <algorithm>
 6 #include <cmath>
 7 #include <string>
 8 
 9 using namespace std;
10 
11 #define N 1005
12 #define ll long long
13 #define mod 7
14 
15 int n,m;
16 int dp[10][10];     //长度为i,以j开头的数目
17 int dir[10];
18 
19 void ini()
20 {
21     memset(dp,0,sizeof(dp));
22     dp[0][0] = 1;
23     int i,j,k;
24     for(i = 1;i < 10 ;i++){
25         for(j = 0;j <= 9 ;j++){
26             if(j == 4) continue;
27             for(k = 0;k <= 9;k++){
28                 if( (k == 4) || (k == 2 && j == 6) ) continue;
29                 dp[i][j] += dp[i-1][k];
30             }
31         }
32     }
33 }
34 
35 int solve(int x)
36 {
37     int re = 0;
38     int len = 0;
39     while(x)
40     {
41         dir[++len] = x % 10;
42         x /= 10;
43     }
44     dir[len+1] = 0;
45     int i,j;
46     for(i = len;i >= 0;i--){
47         for(j = 0;j < dir[i];j++){
48             if(j == 4) continue;
49             if(j == 2 && dir[i+1]==6) continue;
50             re += dp[i][j];
51         }
52         if( (dir[i] == 4) || (dir[i] == 2 && dir[i+1] == 6 ) ) break;
53     }
54     return re;
55 }
56 
57 int main()
58 {
59     //freopen("in.txt","r",stdin);
60     //freopen("out.txt","w",stdout);
61     ini();
62     //scanf("%d",&TT);
63     //while(TT--){
64     while(scanf("%d%d",&n,&m)!=EOF){
65         if(n == 0 && m == 0) break;
66         //scanf("%d",&n);
67         //printf(" %d
",solve(m+1) );
68         printf("%d
",solve(m+1) - solve(n));
69         //cout << mp[ s[ n%294 ] ] << endl;
70     }
71     return 0;
72 }
原文地址:https://www.cnblogs.com/njczy2010/p/5280462.html