跳转至

数位DP

约 203 个字 19 行代码 预计阅读时间 1 分钟

从高位往低位,枚举每一位选什么,记忆化搜索,搜索时需要参数记录高位相关的信息

对于limit,要看情况选择是否记忆化,如果limit=1的状态数远小于limit=0的状态数,那就只记忆化limit=0的状态

区间 [l,r] 统计合法数个数的,通常用前缀和思想,即 ans[1,r]-ans[1,l-1]

常见参数

pos: int,表示当前枚举的位置,一般从高到低

limit: bool,表示枚举的第 pos 位是否受到限制(上限或下限)

last: int,表示上一位填写的值

lead0: bool,表示是否有前导零

sum: int,表示高位的数位和

rem: int,表示高位取模的余数

st: int,表示高位的一些信息(状态压缩)

ll dp[MAXD][...];
ll dfs(int pos, ..., int limit)
{
    if (!pos)
        return ...;
    ll &d = dp[pos][...];
    if (!limit && d != -1) return d;
    ll ans = 0;
    for (int v = (limit ? A[pos] : 9); v >=0 ; --v)
        ans += dfs(pos - 1, ..., limit && A[pos] == v);
    if (!limit) d = ans;
    return ans;
}
ll f(ll x)
{
    int len = 0;
    while (x) A[++len] = x % 10, x /= 10;
    return dfs(len, ..., true);
}