【动态规划】数位DP

数位DP是针对数字的一种动态规划

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
int a[20];
ll dp[20][state];
ll dfs(int pos, /*state变量*/, bool lead, bool limit) //lead是前导零,不是必须,limit是数位上界
{
if (pos == -1) //按位枚举,最低位是0,pos==-1说明这个数我枚举完了
return 1; //返回表示前面的枚举全部合理,已经枚举完了,返回枚举结果
if (!limit && !lead && dp[pos][state] != -1) //记忆化和一些边界
return dp[pos][state];
int up = limit ? a[pos] : 9; //根据limit判断枚举的上界
ll ans = 0;
for (int i = 0; i <= up; i++) //枚举,然后把不同情况的个数加到ans就可以了
{ //分类讨论,根据state进行统计并更新答案
if ()
else if ()
ans += dfs(pos - 1, /*状态转移*/, lead && i == 0, limit && i == a[pos])
}
if (!limit && !lead)
dp[pos][state] = ans;
return ans;
}
ll solve(ll x)
{
int pos = 0;
while (x) //把数位都分解出来
{
a[pos++] = x % 10;
x /= 10;
}
return dfs(pos - 1, /*状态 */, true, true); //刚开始最高位都是有限制并且有前导零的
}
  • state可以定义为数字出现次数