HDU 2089 不要62 (数位DP,入门)

 

 

题意:

  只要含连续的62,或者含4的车牌号码都是不吉利的,其他都是吉利的组合。问区间[L,R]中有多少个数是吉利的?

 

 

思路:

  依然是利用树(10进制是十叉树)的思想,统计左边所有子树有多少个数是吉利的。这道题得先打表,就是暴力打表都不会超时,否则可能超时了。暴力打表可以直接将0~106扫一遍直接找到[0->R]中吉利的有几个,利用前缀和就行了。

  太暴力就没意思了。先用DP处理出吉利的数量以及最高位以2开头的吉利数量,用dp[i][1]表示i位数的吉利数量,dp[i][2]表示i位数且最高位为2的吉利数量。接下来对每个询问的L和R进行统计,差作为答案。看代码就行了,主要是需要考虑得全面一些,明确这一步统计的到底是表示什么。

 

 

 

 

 1 //#include <bits/stdc++.h>
 2 #include <iostream>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <cmath>
 6 #include <map>
 7 #include <algorithm>
 8 #include <vector>
 9 #include <iostream>
10 #define pii pair<int,int>
11 #define INF 0x7f3f3f3f
12 #define LL long long
13 using namespace std;
14 const double PI  = acos(-1.0);
15 const int N=10;
16 
17 int dp[N][N], bit[N], s, t;
18 void pre_cal()
19 {
20     dp[0][1]=1;
21     for(int i=1; i<=7; i++ )
22     {
23         dp[i][1]=9*dp[i-1][1]-dp[i-1][2]; //吉利(包括0开头)
24         dp[i][2]=dp[i-1][1];              //最高位含2:已经扣除不吉利的了
25     }
26 }
27 
28 
29 int cal(int n)  //计算区间[0~n]吉利的数量
30 {
31     memset(bit,0,sizeof(bit));
32     int len=0;
33     while(n)
34     {
35         bit[++len]=n%10;
36         n/=10;
37     }
38     int ans=0, i;
39     for(i=len ;i>0; i--)
40     {
41         ans+=dp[i-1][1]*bit[i];
42         if(bit[i]>4)    ans-=dp[i-1][1];
43         if(bit[i+1]==6&&bit[i]>2)   ans-=dp[i-1][1];
44         if(bit[i]>6)    ans-=dp[i-1][2];    //注意点!
45         if(bit[i+1]==6&&bit[i]==2||bit[i]==4)  break;
46     }
47     if(i==0)    ans++;  //n本身是否吉利?
48     return ans;
49 }
50 
51 int main()
52 {
53     //freopen("input.txt","r",stdin);
54     pre_cal();
55     while(scanf("%d%d",&s,&t), s+t)
56         printf("%d\n",cal(t)-cal(s-1));
57     return 0;
58 }
AC代码

 

posted @ 2015-10-02 17:21  xcw0754  阅读(137)  评论(0编辑  收藏  举报