zoukankan      html  css  js  c++  java
  • 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

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

  • 相关阅读:
    php 为什么new一个对象后面要加一个反斜杠
    c# 判断当前时间是否在某一时间段内
    关于Entity Framework的概念及搭建
    mvc 读写txt文档
    winform :DataGridView添加一列checkbox
    使用filter进行登录验证,并解决多次重定向问题
    关于Select选中问题
    错误:Parameter '0' not found.Available parameters are [arg1, arg0, param1, param2]的解决方法
    sql-省市区
    设置oracle主键自增长
  • 原文地址:https://www.cnblogs.com/lv-anchoret/p/8467126.html
Copyright © 2011-2022 走看看