← [ BACK_TO_NOTES ]

数位 DP

数位 DP 入门:按位枚举数字,在“是否贴上界”和“前导零”约束下做记忆化搜索。

#algorithm #concept #growing #dp

[!info] related notes 动态规划

数位 DP

一句话

把一个数字拆成十进制位,从高位到低位枚举,在“是否受上界限制”的条件下统计满足条件的数字个数。

识别信号

  • 求区间 [0, n] 或 [l, r] 里有多少个数满足某种数位条件
  • 条件和“每一位”有关,比如:
    • 不含某个数字
    • 数位和为多少
    • 邻位关系限制

常见状态

dfs(pos, limit, started, state)
  • pos:当前处理到第几位
  • limit:这一位是否受上界约束
  • started:前面是否已经填过非前导零
  • state:题目附加状态(数位和、前一位、出现次数等)

为什么常写成记忆化搜索

数位 DP 更自然的写法通常是递归:

  • 枚举当前位填什么
  • 把限制和状态传给下一位

只有在 limit = false 且 started 等条件稳定时,才缓存答案。

通用模板

function dfs(pos, limit, started, state) {
    if (pos === digits.length) {
        return ...;
    }

    if (!limit && memo.has(key)) return memo.get(key);

    const up = limit ? digits[pos] : 9;
    let ans = 0;

    for (let d = 0; d <= up; d++) {
        ans += dfs(pos + 1, limit && d === up, started || d !== 0, nextState);
    }

    if (!limit) memo.set(key, ans);
    return ans;
}

高频坑

  • 把前导零当成正常数字参与限制
  • limit 为真时错误地缓存,导致状态污染
  • 求区间 [l, r] 时忘了转成 solve(r) - solve(l - 1)
创建于 2026/3/18 更新于 2026/7/15
Digital Biome
Access

键盘导航

j / k / ↑ / ↓
选择对象
Enter / o
打开选择
/ 或 Ctrl+K
全站搜索
i / f / 1–4
筛选当前列表
g → h / l / p / t / a
首页 / 笔记 / 项目 / 工具 / About
r → 1–9
打开所选对象的关联
u
返回上一页
Esc
关闭浮层 / 取消命令;输入框内清空文本