数位dp模板
数位dp模板
模板
应用:求某个区间[l, r]中,满足某个条件的数的个数
思路:
- 函数f(x)求[0, x]合法的数的个数,答案为f(r) - f(l-1)
- 从高位向低位枚举,每一位t可以划分为两个分支,左分支为0,1,…,t-1,右分支为t
- 预处理左分支的所有合法个数,递归处理右分支
- 不重不漏动态规划[0, x]所有数
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
using namespace std;
typedef long long ll;
const ll N = 30;
// f[i][j]:用于左分支
ll f[N][N];
// 预处理f
void init(){}
ll dp(ll n)
{
// 边界特判
if (n == 0) return ;
// 划分出每一位
vector<ll> nums;
while (n) nums.push_back(n % 10), n /= 10;
// res:答案 last:与已经枚举完的数的相关信息
ll res = 0, last = -2;
// 从高位到低位枚举
for (int i = nums.size() - 1; i >= 0; i--)
{
// 取出每一位数
ll x = nums[i];
// 左分支
for (ll j = 0; j <= x - 1; j++)
if ()
res += f[][];
// 判断是否合法
if () // 更新last
else break; //接下来右分支的所有数都不合法
// 最右下角分支
if (i == 0)
res++;
}
// 特殊处理
return res;
}
int main()
{
init();
ll l, r;
scanf("%lld%lld", &l, &r);
//[0, r]合法数 - [0, l - 1]合法数
printf("%lld\n", dp(r) - dp(l - 1));
return 0;
}
题目
1 |
|
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 lswtn!