Hdu 2089 不要62 (数位dp入门题目)

题目链接:

  Hdu 2089 不要62

题目描述:

  给一个区间 [L, R] ,问区间内不含有4和62的数字有多少个?

解题思路:

  以前也做过这个题目,但是空间复杂度是n。如果数据范围太大就GG了。今天看了一下数位DP,的确有时间和空间上的优越性。
  用数位dp做这个题目的时候,首先要预处理出dp[x][y],代表以y开头的x位数中不含有62和4的数有多少个,在满足条件的情况下状态转移为:dp[x][y] += dp[x-1][k]。又因为对于一个数字x,如果和它位数相同的数字y小于x,那么只需要y数字其中任意一位小于x即可。然后问题就变为求ans([1, r+1]) - ans([1, l])。

 1 #include <vector>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <iostream>
 5 #include <algorithm>
 6 using namespace std;
 7 
 8 const int maxn = 10;
 9 int dp[maxn][maxn];
10 //dp[x][y] 以y开头的x位数满足题意的个数
11 
12 void init ()
13 {
14     memset(dp, 0, sizeof(dp));
15     dp[0][0] = 1;
16     for (int i=1; i<=7; i++)//i位数
17         for (int j=0; j<10; j++)//第i位数
18             for (int k=0; k<10; k++)//第i-1位数
19             {
20                 if(j==4 || j==6&&k==2)
21                     continue ;
22                 dp[i][j] += dp[i-1][k];
23             }
24 }
25 
26 int solve (int n)
27 {
28     int a[maxn], len = 0, ans = 0;
29     while (n)
30     {
31         a[++len] = n % 10;
32         n /= 10;
33     }
34     a[len+1] = 0;
35 
36     for (int i=len; i>0; i--)
37     {//枚举后len位的策略
38         for (int j=0; j<a[i]; j++)
39         {
40             if (j==4 || a[i+1]==6&&j==2)
41                 continue ;
42             ans += dp[i][j];
43         }
44 
45         if (a[i]==4 || a[i+1]==6 && a[i]==2)
46             break;
47     }
48     return ans;
49 }
50 
51 int main ()
52 {
53     int n, m;
54     init ();
55 
56     while (scanf ("%d %d", &n, &m), n + m)
57         printf ("%d\n", solve(m+1) - solve(n));
58     return 0;
59 }

 

posted @ 2015-10-28 16:01  罗茜  阅读(315)  评论(0编辑  收藏  举报