本文主要內容:數位DP例題
數位DP
主要有兩種方法,填數法和記搜。這裡主要研究記搜的實現;
模板
相比於填數法,記搜的優點在於有固定的模板,實現較容易;
缺點在於需要很多 $ memset $,常數較大,容易被卡;
下面透過幾道例題來了解記搜模板;
一 $ haha $ 數
設記搜各引數如下:
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;
}
也是水了一篇