数位dp题目总结

数位dp

题目知识点难度
2376. 统计特殊整数数位dp模板困难
600. 不含连续1的非负整数数位dp困难
233. 数字1的个数数位dp模板题困难
902. 最大为N的数字组合数位dp模板题目困难
数字1的个数mask记录数字x的个数
acwing 1081 度的数量使用进制思想 + 每一位是1或者0。mask记录1的个数
acwing 1082、1083 ,1085Mask记录前位的数是多少
acwing 1084mask记录前面数字的和

数位dp做题思路

先将[a, b]区间改成从[0, a], [0, b]的单个计算。然后做差

其次使用标准模板代码就行了

标准模板代码,根据题目限定的条件,修改pre这一个状态变量就行了。

常见的状态变量有

  1. 前一位,这个题目中有相邻位之间约数的情况。比如 acwing的1082, 1083, 1085
  2. 位数之和,参考acwing 1084的情况
  3. mask,1-9中数字不能重复。mask记录选择了那个数字
  4. c n t x cnt_x cntx , x出现的次数,用于统计出现的次数。 参考数字1的个数
    private static int dfs(int cur, int pre, boolean isNum, boolean isLimit) {
        if (cur == s.length) {
            return isNum ? 1 : 0;
        }
        // 记忆化
        int res = dp[cur][pre];
        if (isNum && !isLimit && res >= 0)
            return res;
        res = 0;
        // 不是数字,可以跳过
        if (!isNum) res += dfs(cur + 1, pre, false, false);
        // 枚举是数字的情况
        int up = isLimit ? s[cur] - '0' : 9;
        for (int i = isNum ? 0 : 1; i <= up; i++) {
            if (i == 4 || (pre == 6 && i == 2)) continue;
            res += dfs(cur + 1, i, true, isLimit && i == up);
        }
        // 记录
        if (!isLimit && isNum) dp[cur][pre] = res;
        return res;
    }
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值