[DP] 数位DP

本文主要内容:数位DP例题

数位DP

主要有两种方法,填数法和记搜。这里主要研究记搜的实现;

模板

相比于填数法,记搜的优点在于有固定的模板,实现较容易;

缺点在于需要很多 $ memset $,常数较大,容易被卡;

下面通过几道例题来了解记搜模板;

一 $ haha $ 数

image

设记搜各参数如下:

long long dfs(int x, int gcd, bool limit, int st)

$ gcd $ 代表各位数字的最小公倍数,$ limit $ 代表当前位有没有到达最高位限制,$ st $ 代表现在的数 $ mod \ 2520 $ 的结果($ 2520 $ 是数字$ 1 \ to \ 9 $ 的和);

$ gcd $ 可以离散化($ 2520 $ 的因数最多只有不到 $ 50 $ 个);

long long dfs(int x, int gcd, bool limit, int st) {
	if (x > cnt) return st % gcd == 0;
	if (!limit && f[cnt - x + 1][vis[gcd]][st] != -1) return f[cnt - x + 1][vis[gcd]][st];
	int res = limit ? a[cnt - x + 1] : 9; //判断现在的限制;
	long long ret = 0;
	for (register int i = 0; i <= res; i++) {
		if (i == 0) ret += dfs(x + 1, gcd, limit && i == res, st * 10 % mod); //特判0;
		else ret += dfs(x + 1, gcd * i / __gcd(gcd, i), limit && i == res, (st * 10 + i) % mod);
	}
	return limit ? ret : f[cnt - x + 1][vis[gcd]][st] = ret;
}

也是水了一篇

posted @ 2024-07-14 08:56  Peppa_Even_Pig  阅读(17)  评论(0编辑  收藏  举报