O-Bomb(数位dp)

Bomb

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)
Total Submission(s): 15062    Accepted Submission(s): 5437


Problem Description
The counter-terrorists found a time bomb in the dust. But this time the terrorists improve on the time bomb. The number sequence of the time bomb counts from 1 to N. If the current number sequence includes the sub-sequence "49", the power of the blast would add one point.
Now the counter-terrorist knows the number N. They want to know the final points of the power. Can you help them?
 
Input
The first line of input consists of an integer T (1 <= T <= 10000), indicating the number of test cases. For each test case, there will be an integer N (1 <= N <= 2^63-1) as the description.

The input terminates by end of file marker.
 
Output
For each test case, output an integer indicating the final points of the power.
 
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.
 
 
//题意 t 组数据,在 1- n 中出现了49的数据个数,n 很大,2^63-1 , 遍历肯定不行。
 
//听说这是数位dp的一道水题,这也是水题吗,我服了
自己想了一阵,只想到了一点点。看了别人的也看了很久,才明白,这篇博客非常详细,我就不赘述了,认真看一定能看懂。
我的与他的dp数组有细微差别,因为我自己理解了写了一遍,稍微注意一下。
 
代码 15ms
 
 1 #include <stdio.h>
 2 #include <string.h>
 3 
 4 __int64 dp[25][3];
 5 //dp[i][0]   含49,数的个数
 6 //dp[i][1] 不含49,但首位是9的数的个数
 7 //dp[i][2] 不含49,数的个数(包含了首位是9的数的个数)
 8 void Init()
 9 {
10     dp[0][2]=1;
11     for (int i=1;i<=24;i++)
12     {
13         dp[i][0]=dp[i-1][0]*10+dp[i-1][1];
14         dp[i][1]=dp[i-1][2];
15         dp[i][2]=dp[i-1][2]*10-dp[i-1][1];
16     }
17 }
18 
19 __int64 solve(__int64 n)
20 {
21     __int64 a[25],len=0;
22 
23     while (n)
24     {
25         a[++len]=n%10;
26         n/=10;
27     }
28     a[len+1]=0;
29 
30     __int64 ans=0;
31     int flag=0;
32 
33     for (int i=len;i>0;i--)
34     {
35         ans+=dp[i-1][0]*a[i];
36         if (flag)           //前面有49就所有情况都是49数了
37             ans+=dp[i-1][2]*a[i];
38         if (!flag&&a[i]>4)  //加上4  9... 的情况
39             ans+=dp[i-1][1];
40         if (a[i]==9&&a[i+1]==4)//判断是不是 49 
41             flag=1;
42     }
43     return ans;
44 }
45 
46 int main()
47 {
48     int t;
49     __int64 n;
50     Init();
51     scanf("%d",&t);
52     while (t--)
53     {
54         scanf("%I64d",&n);
55         printf("%I64d
",solve(n+1));//因为函数功能是 (0,n) 区间的49数,题目要求的是[1,n],所以+1
56     }
57     return 0;
58 }
View Code
 
原文地址:https://www.cnblogs.com/haoabcd2010/p/5753732.html