HDU 3555 Bomb (数位DP)

题目链接http://acm.hdu.edu.cn/showproblem.php?pid=3555

题目大意:从0开始到给定的数字N所有的数字中遇到“49”的数字的个数。

Sample Input
3
1
50
500
 
Sample Output
0
1
15
Hint
From 1 to 500, the numbers that include the sub-sequence "49" are "49","149","249","349","449","490","491","492","493","494","495","496","497","498","499", so the answer is 15.

分析:定义dp[25][3]

dp[len][0] 表示前len位没有49的数字的个数
dp[len][1] 表示前len位没有49但是以9结尾的数的个数
dp[len][2] 表示前len位有49的状态 

代码如下:

 1 # include<stdio.h>
 2 # include<string.h>
 3 __int64 dp[25][3],N;
 4 int digit[25];
 5 void init(){
 6     memset(dp,0,sizeof(dp));
 7     dp[0][0] = 1;
 8     for(int i =1; i<=20; i++){
 9         dp[i][0] = dp[i-1][0]*10 - dp[i-1][1];
10         //①:dp[i-1][0]*10代表当前可选择0-9十个数 ②:dp[i-1][1]当前以9开头的数的个数。  
11         //③dp[i-1][0]*10-dp[i-1][1]代表不包含49的个数。  
12         dp[i][1] = dp[i-1][0];
13         //①dp[i-1][0]代表以9开头的个数的数目  
14         dp[i][2] = dp[i-1][2]*10 + dp[i-1][1];
15         //以49开头的个数(分为两种情况:①dp[i][2]:x49xxx  ②当第一个x为4时满足条件dp[i][1]x9xxxx  
16     }
17 }
18 int main(){
19     init();
20     int T,len,flag,i;
21     __int64 ans;
22     scanf("%d",&T);
23     while(T--){
24         flag = ans = 0;
25         scanf("%I64d",&N);
26         N++;
27         memset(digit,0,sizeof(digit));
28         len = 1;
29         while(N){    //逆序存放
30             digit[len++] = N%10;
31             N /= 10;
32         }
33         for(i=len-1; i>0; i--){
34             ans += digit[i] * dp[i-1][2];    //开头为x49的个数
35             if(flag)
36                 ans += digit[i]*dp[i-1][0];    //开头为49的个数
37             else if(!flag && digit[i]>4)
38                 ans += dp[i-1][1];    //开头我x9(x>4)的个数
39             if(digit[i+1]==4 && digit[i]==9)
40                 flag = 1;
41         }
42         printf("%I64d\n",ans);
43     }
44     return 0;
45 }

 

 

 

你可能感兴趣的:(HDU)