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 }
把每一件简单的事情做好,就是不简单;把每一件平凡的事情做好,就是不平凡!相信自己,创造奇迹~~