牛客-送分了QAQ——数位dp的运用题

Posted C+++++++++++++++++++

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了牛客-送分了QAQ——数位dp的运用题相关的知识,希望对你有一定的参考价值。

题目

题目链接

题目详解

  • 数位dp问题,两步走:1.转数组。2.开始记忆化搜索。

记忆化搜索和当前位是否是限制状态,以及计数状态是否相同。

  1. state==0则表示到当前位置还未出现4/3/8。
  2. state==1则表示到当前位置的前一个位置已经出现3。
  3. state==2则表示到当前位置已经出现4或者连续的38。

解题代码

#include <bits/stdc++.h>

using namespace std;
//TODO 数位dp两步:一、把数字转数组。二、通过记忆化dfs计算(记忆化重点在:是否处于限制状态以及当前的计数状态)。

//TODO 三个状态:
// state==0则表示到当前位置还未出现4/3/8
// state==1则表示到当前位置的前一个位置已经出现3
// state==2则表示到当前位置已经出现4或者连续的38

int a[20];//用于转的数组
int memo[15][3];//用于记忆化的备忘录


int dp(bool limit, int pos, int state) 
    if (pos == 0)return state == 2;
    if (!limit && memo[pos][state])return memo[pos][state];
    int up = limit ? a[pos] : 9;
    int ret = 0;
    for (int i = 0; i <= up; ++i) 
        if (i == 4 || state == 2 || (i == 8 && state == 1)) 
            ret += dp(limit && i == up, pos - 1, 2);
         else if (i == 3) 
            ret += dp(limit && i == up, pos - 1, 1);
         else 
            ret += dp(limit && i == up, pos - 1, 0);
        
    
    if (!limit)memo[pos][state] = ret;
    return ret;


int to_cal(int num) 
    int pos = 0;
    while (num) 
        a[++pos] = num % 10;
        num /= 10;
    
    return dp(1, pos, 0);



int main() 
    ios::sync_with_stdio(false);
    int c, d;
    int l, r;
    while (cin >> c >> d) 
        if (c == 0 && d == 0)
            return 0;
        l = to_cal(c - 1);
        r = to_cal(d);
        cout << r - l << '\\n';
    
    return 0;

以上是关于牛客-送分了QAQ——数位dp的运用题的主要内容,如果未能解决你的问题,请参考以下文章

牛客每日一题 和与或 数位dp+状态压缩

(计数器)NOIP模拟赛(神奇的数位DP题。。)

牛客白月赛7题解

牛客白月赛31题解

数位dp对于状态描述与发现的一些感悟

牛客挑战赛51 C.NIT的数(数位dp)