HDU3555 区间的数里面有49的个数(数位dp)

题目:区间的数里面有49的个数

分析:

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

 

一开始我是打算先算不满足的,在算满足的;结果不行,可能这样算出来的数太大了所以不行吧;

通过这道题可以更加理解了(不要62)这个题目的sta 的表示 , 原来如此呀

#include<stdio.h>
#include<string.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));
    }
}
View Code

 

posted @ 2018-11-08 16:50  shuai_hui  阅读(217)  评论(0编辑  收藏  举报