Skip to content

Commit

Permalink
Update 数位dp.md
Browse files Browse the repository at this point in the history
重构
  • Loading branch information
CurryWOE authored Oct 30, 2023
1 parent c3cf47d commit 37bd684
Showing 1 changed file with 34 additions and 7 deletions.
41 changes: 34 additions & 7 deletions docs/Dp/数位dp.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,41 @@
# 数位DP
从高位往低位,枚举每一位选什么,记忆化搜索,搜索需要参数记录前缀相关的信息
从高位往低位,枚举每一位选什么,记忆化搜索,搜索时需要参数记录高位相关的信息

只记忆化不贴着上界没有前导0的情况
对于limit,要看情况选择是否记忆化,如果limit=1的状态数远小于limit=0的状态数,那就只记忆化limit=0的状态

区间 [l,r] 统计合法数个数的,通常用前缀和思想,即 ans[1,r]-ans[1,l-1]
## 前缀相关信息
区间限制:高位选择是否贴着区间上限,如果不贴着,该位可以随便选,否则不能超过区间上限
## 常见参数
pos: int,表示当前枚举的位置,一般从高到低

前导0:当该位及高位都是0,那么该位是前导0,如果统计的是digit,不计入答案
limit: bool,表示枚举的第 pos 位是否受到限制(上限或下限)

hdu2089不要62:上一位选的什么
last: int,表示上一位填写的值

洛谷P2602:当前要计算的数字,在高位选择了多少个
lead0: bool,表示是否有前导零

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

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

st: int,表示高位的一些信息(状态压缩)
```cpp
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);
}
```

0 comments on commit 37bd684

Please sign in to comment.