Bomb HDU 3555 dp状态转移

Posted 林兮

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Bomb HDU 3555 dp状态转移相关的知识,希望对你有一定的参考价值。

 

题目:http://acm.hdu.edu.cn/showproblem.php?pid=3555

题意:

给出一个正整数N,求出1~N中含有数字“49”的数的个数

思路:

采用数位dp的状态转移方程法解

具体如下:

dp[len][state];  dp数组的第一位代表数字的位数,第二位代表状态

状态设定:

dp[i][0] : i 位数字中不含数字49的数的个数

dp[i][1] : i 位数字中不含数字49,但高位是9的数的个数

dp[i][0] : i 位数字中含有数字49的数的个数

状态转移方程:

dp[i][0] = dp[i-1][0] * bit[i] - dp[i-1][1];长度为 i 不含49的数的个数 = 长度为 i-1 中不含49的数的个数*当前数字(因为这个位置可以填0~bit[i]-1),然而,其中包含了bit[i]为4且长度为 i-1 的高位为9,从而组成49····的情况,所以,减去长度为 i-1 的高位为9的数的个数,dp[i-1][1] * 1(这个1代表的是bit[i]为4的情况。

dp[i][1] = dp[i-1][0];长度为 i 的高位为9但不含49的数的个数 = 长度为 i-1 中不含49的数的个数(因为只需在此基础上加上9即可构成 i 位最高位为9的情况)。

dp[i][2] = dp[i-1][2] * bit[i] + dp[i-1][1];长度为 i 的含有数字49的数的个数 = 长度为 i-1 的个数*当前数字,加上长度为 i-1 的高位为9的数字的个数(加个4就成了i位含49的数了)。

 

代码如下:

#include<iostream>
using namespace std;

int n, bit[20];
unsigned long long dp[20][3], num, ans;

void init()
{
    dp[0][0] = 1;
    for (int i = 1; i < 20; ++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];
    }
}

long long solve()
{
    int len = 0, last = 0;
    bool flag = false;
    num++, ans = 0;
    while (num)
    {
        bit[++len] = num % 10;
        num /= 10;
    }
    for (int i = len; i > 0; --i)
    {
        ans += dp[i - 1][2] * bit[i];
        if (flag)ans += dp[i - 1][0] * bit[i];
        if (!flag&&bit[i] > 4)ans += dp[i - 1][1];
        if (last == 4 && bit[i] == 9)flag = true;
        last = bit[i];
    }
    return ans;
}

int main()
{
    cin >> n;
    init();
    while (n--)
    {
        cin >> num;
        cout << solve() << endl;
    }
    return 0;
}

 

num++的原因是,该方式求的是开区间,而题目为闭区间,所以要+1

 

感谢您的阅读,生活愉快~

以上是关于Bomb HDU 3555 dp状态转移的主要内容,如果未能解决你的问题,请参考以下文章

HDU 3555 Bomb (数位DP)

Hdu3555 Bomb(数位DP)

hdu 3555 Bomb 数位DP

HDU 3555Bomb 数位DP

Bomb HDU - 3555 (数位DP)

HDU - 3555 - Bomb(数位DP)