HDU 3555 - Bomb - [数位DP]

题目链接:

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)

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.
 
 
题意:求出[1,n]中多少个数包含49;

 

题解:类似于HDU 2089,另外关于dp数组的定义如下:

dp[pos][0]:长度为pos的数中,不包含49的,前一位不为4的有多少个;
dp[pos][1]:长度为pos的数中,不包含49的,前一位为4的有多少个;
dp[pos][2]:长度为pos的数中,包含49的有多少个;

 

AC代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int dig[20];
ll dp[20][3];
/*
dp[pos][0]:长度为pos的数中,不包含49的,前一位不为4的有多少个;
dp[pos][1]:长度为pos的数中,不包含49的,前一位为4的有多少个;
dp[pos][2]:长度为pos的数中,包含49的有多少个;
*/
ll dfs(int pos,int pre,bool have49,bool limit)
{
    if(pos==0) return have49;
    if(!limit)//首先满足没有上界限制
    {
        if(have49 && ~dp[pos][2]) return dp[pos][2];
        if(!have49 && pre==4 && ~dp[pos][1]) return dp[pos][1];
        if(!have49 && pre!=4 && ~dp[pos][0]) return dp[pos][0];
    }

    int up=limit?dig[pos]:9;
    ll ans=0;
    for(int i=0;i<=up;i++)
    {
        if(pre==4 && i==9) ans+=dfs(pos-1,i,1,limit && i==up);
        else ans+=dfs(pos-1,i,have49,limit && i==up);
    }

    if(!limit)
    {
        if(have49) dp[pos][2]=ans;
        else
        {
            if(pre==4) dp[pos][1]=ans;
            else dp[pos][0]=ans;
        }
    }

    return ans;
}
ll solve(ll x)
{
    int pos=0;
    while(x)
    {
        dig[++pos]=x%10;
        x/=10;
    }
    return dfs(pos,0,0,1);
}

int main()
{
    int T;
    ll N;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%I64d",&N);
        memset(dp,-1,sizeof(dp));
        printf("%I64d\n",solve(N));
    }
}

 

posted @ 2018-03-03 17:12  Dilthey  阅读(438)  评论(0编辑  收藏  举报