Sweety

Practice makes perfect

导航

HDU 3555 Bomb (数位DP)

Posted on 2017-04-27 21:30  蓝空  阅读(129)  评论(0编辑  收藏  举报

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.
        
 


题意:

数出含有49的个数

here一样

#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define BITNUM 20
#define MAXN 10
LL dp[BITNUM][MAXN];
int bits[BITNUM];

///len数字的位数,digit标记状态的值(注意压缩抽象),limit 表示digit是否是第len位(从低位向高位数,个位为第1位)的范围边界
LL dfs(int pos, int digit, bool end_flag)
{
    if (!end_flag  && dp[pos][digit] != -1)///记忆化搜索,如果之前已经求出来了,则返回。注意这里要求 end_flag为false
        return dp[pos][digit];
    if(pos==0) return dp[pos][digit]=1;


    int end = end_flag ? bits[pos-1] : 9 ;///如果当前位是边界数字N对应位的最大值,则下一位的范围只能从0到边界数字N的下一位的最大值。否则为0 到 9
    LL ans = 0;
    for(LL i = 0; i <= end; i++)
    {
        if(!(digit==4&&i==9))
            ans += dfs(pos - 1, i, end_flag && (i==end));
    }


    if (!end_flag) ///digit不是第len位的最高范围,则可以将结果缓存
        dp[pos][digit] = ans;
    return ans;
}


LL solve(LL  x)
{
    memset(bits,0,sizeof bits);
    int pos=0;
    while(x)
    {
        bits[pos++]=x%10;
        x/=10;
    }
    return dfs(pos, bits[pos], 1);///为方便当前为设置为0
}

int main()
{
    memset(dp,-1,sizeof dp);
    int T;
    LL n;
    scanf("%d",&T);
    while(T--)
    {
       scanf("%lld",&n);
       printf("%lld\n",(n+1)-solve(n));
    }
    return 0;
}