hdu 2089 不要62 hdu 3555 Bomb (数位DP)

hdu 2089 不要62

题意:给出两个数,求区间内不带4和62的数的个数。(PS:62是连续的两位)

思路:

dp[i][0]表示前i位不含不吉利数的个数(如i=4,则范围为0~9999,下同)

dp[i][1]表示前i位不含不吉利数且首位是2的数的个数

dp[i][2]表示前i位含不吉利数的数的个数。

则有

dp[i][0] = dp[i-1][0] * 9 - dp[i-1][1]

dp[i][1] = dp[i-1][0]

dp[i][2] = dp[i-1][2] * 10 + dp[i-1][0] + dp[i-1][1] 

预处理得到dp数组

 

然后从高往低逐位求答案。

例子,如数5678

0~4999

5000~5599

5600~5669

5670~5678

的顺序求解。 

 

最低位处处理要特别留意。

参考:http://blog.csdn.net/acm_cxlove/article/details/7819907 

 

 1 #include <cstdio>
 2 #include <cstring>
 3 
 4 int dp[10][3], bit[10];
 5 
 6 void init()
 7 {
 8 
 9     dp[1][0] = 9; dp[1][1] = 1; dp[1][2] = 1;
10     for(int i=2; i<=6; i++)
11     {
12         dp[i][0] = dp[i-1][0] * 9 - dp[i-1][1];
13         dp[i][1] = dp[i-1][0];
14         dp[i][2] = dp[i-1][0] + dp[i-1][1] + dp[i-1][2] * 10;
15     }
16 }
17 
18 int solve(int n)
19 {
20     memset(bit, 0sizeof(bit));
21     int len = 0;
22     while(n>0)
23     {
24         bit[++len] = n%10;
25         n /= 10;
26     }
27     bit[len+1] = 0;
28     int ret = 0, flag = 0;
29     for(int i=len; i>=2; i--)
30     {
31         ret += dp[i-1][2] * bit[i];
32         if(flag==1)
33             ret += dp[i-1][0] * bit[i];
34         if(flag==0 && bit[i]>4)
35             ret += dp[i-1][0];
36         if(flag==0 && bit[i+1]==6 && bit[i]>2)
37             ret += dp[i][1];
38         if(flag==0 && bit[i]>6)
39             ret += dp[i-1][1];
40         if(bit[i]==4 || bit[i]==2 && bit[i+1]==6)
41             flag = 1;
42     }
43     if(flag==1) ret += bit[1] + 1;
44     if(flag==0 && bit[1]>=4) ret++;
45     if(flag==0 && bit[1]>=2 && bit[2]==6) ret++;
46     return ret;
47 }
48 
49 int main()
50 {
51     int l, r;
52     init();
53 /*
54     for(int i=1; i<=6; i++)
55     {
56         for(int j=0; j<=2; j++)
57             printf("%d ",dp[i][j]);
58         printf("\n");
59     }
60 */
61     while(scanf("%d%d",&l,&r)!=EOF)
62     {
63         if(l==0 && r==0break;
64 
65         if(l>r)
66         {
67             int temp;
68             temp = l; l = r; r = temp;
69         }
70         int ans = solve(r) - solve(l-1);
71         //printf("%d %d %d\n",solve(l),solve(r),ans);
72         printf("%d\n",r-l+1-ans);
73     }
74     return 0;
75 }
View Code

 

hdu3555

 1 #include <cstdio>
 2 #include <cstring>
 3 
 4 __int64 dp[25][3];
 5 int bit[25];
 6 
 7 void init()
 8 {
 9     dp[1][0] = 10; dp[1][1] = 1; dp[1][2] = 0;
10     for(int i=2; i<=19; i++)
11     {
12         dp[i][0] = dp[i-1][0] * 10 - dp[i-1][1]; //不含49数
13         dp[i][1] = dp[i-1][0]; //不含49首位为9的数
14         dp[i][2] = dp[i-1][1] + dp[i-1][2]*10//含49数
15     }
16 }
17 
18 __int64 solve(__int64 n)
19 {
20     int len = 0;
21     while(n>0)
22     {
23         bit[++len] = n%10;
24         n /= 10;
25     }
26     bit[len+1] = 0;
27 
28     __int64 ret = 0;
29     int flag = 0;
30     for(int i=len; i>=2; i--)
31     {
32         ret += dp[i-1][2] * bit[i];
33         if(flag==1)
34             ret += dp[i-1][0] * bit[i];
35         if(flag==0 && bit[i]>4)
36             ret += dp[i-1][1];
37         if(bit[i+1]==4 && bit[i]==9)
38             flag = 1;
39     }
40     if(flag==1) ret += bit[1] + 1;                 //这两行调很久
41     if(flag==0 && bit[2]==4 && bit[1]==9) ret++;
42     return ret;
43 }
44 
45 int main()
46 {
47     int t;
48     __int64 n;
49     init();
50     scanf("%d",&t);
51     while(t--)
52     {
53         scanf("%I64d",&n);
54         printf("%I64d\n",solve(n));
55     }
56     return 0;
57 }
View Code

 

posted @ 2014-02-23 16:28  byluoluo  阅读(196)  评论(0编辑  收藏  举报