HDU 3555 Bomb (数位dp)

题意:求【1,n】当中包含49的一共有多少个数字?

思路:用dp[i][0]来表示 数字位数小于等于i并且不包含49的数字个数,之所以说小于等于而不是严格等于因为有可能有前导零。

dp[i][1]表示 数字位数等于i 并且开头为9,不含“49” 的个数。

dp[i][2] 表示数字位数小于等于i并且包含“49”的个数

初始化完成之后,那么计算给定的n,统计的时候就是对于n的每一位(从高到低)

假设当前是第i位(最右边为第1位),那么这一位的贡献肯定有 dp[i - 1][2] * digit[i];再者,如果这一位大于4的话,那么一定可以贡献出来一个4对应后面的9开头的 从而组成符合条件的数,所以再加上dp[i - 1][1], 如果前面有49了,那么后面的一定是加起来所有的就是(dp[i - 1][2] + dp[i - 1][0]) * digit[i],因为刚开始加过dp[i - 1][2],所以这里直接加dp[i -1][0]就行了。

/*************************************************************************
    > File Name:            bomb.cpp
    > Author:               Howe_Young
    > Mail:                 1013410795@qq.com
    > Created Time:         2015年09月15日 星期二 18时38分25秒
 ************************************************************************/

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>

using namespace std;
typedef long long ll;
const int maxn = 23;
ll dp[maxn][3];
//dp[i][0] representation the length less than or equal i not include 49 (may be start with 9, but not include 49)
//dp[i][1] representation the length equal i and not include 49 but start with 9
//dp[i][2] representation the length less than or equal i include 49
void init()
{
    dp[0][0] = 1;
    for (int i = 1; i <= 21; i++)
    {
        dp[i][0] = dp[i - 1][0] * 10 - dp[i - 1][1];
        dp[i][1] = dp[i - 1][0];
        dp[i][2] = dp[i - 1][2] * 10 + dp[i - 1][1];
    }
}

ll get_cnt(ll n)
{
    int digit[maxn], tot = 0;
    while (n)
    {
        digit[++tot] = n % 10;
        n /= 10;
    }
    digit[tot + 1] = 0;
    ll ans = 0;
    bool flag = false;
    for (int i = tot; i >= 1; i--)
    {
        ans += digit[i] * dp[i - 1][2];
        if (flag)
            ans += digit[i] * dp[i - 1][0];
        else 
        {
            if (digit[i] > 4) ans += dp[i - 1][1];
            if (digit[i + 1] == 4 && digit[i] == 9) flag = true;
        }
    }
    if (flag) ans++;
    return ans;
}
int main()
{
    init();
    int T; ll n;
    scanf("%d", &T);
    while (T--)
    {
        cin >> n;
        cout << get_cnt(n) << endl;
    }
    return 0;
}

 

posted @ 2015-09-15 20:44  Howe_Young  阅读(198)  评论(0编辑  收藏  举报