数位dp模板
1.0版本
class Solution {
public:
int countDigitOne(int n) {
auto s = to_string(n);
int m = s.length(), dp[m][m];
memset(dp, -1, sizeof(dp));
function<int(int, int, bool)> f = [&](int i, int cnt1, bool is_limit) -> int {
if (i == m) return cnt1;
if (!is_limit && dp[i][cnt1] >= 0) return dp[i][cnt1];
int res = 0;
int up = is_limit ? s[i] - '0' : 9;
for (int d = 0; d <= up; ++d) // 枚举要填入的数字 d
res += f(i + 1, cnt1 + (d == 1), is_limit && d == up);
if (!is_limit) dp[i][cnt1] = res;
return res;
};
return f(0, 0, true);
}
};
作者:灵茶山艾府
链接:https://leetcode.cn/problems/number-of-digit-one/solutions/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
2.0版本
class Solution {
public:
long long numberOfPowerfulInt(long long start, long long finish, int limit, string s) {
string low = to_string(start);
string high = to_string(finish);
int n = high.size();
low = string(n - low.size(), '0') + low; // 补前导零,和 high 对齐
int diff = n - s.size();
vector<long long> memo(n, -1);
function<long long(int, bool, bool)> dfs = [&](int i, bool limit_low, bool limit_high) -> long long {
if (i == low.size()) {
return 1;
}
if (!limit_low && !limit_high && memo[i] != -1) {
return memo[i]; // 之前计算过
}
// 第 i 个数位可以从 lo 枚举到 hi
// 如果对数位还有其它约束,应当只在下面的 for 循环做限制,不应修改 lo 或 hi
int lo = limit_low ? low[i] - '0' : 0;
int hi = limit_high ? high[i] - '0' : 9;
long long res = 0;
if (i < diff) { // 枚举这个数位填什么
for (int d = lo; d <= min(hi, limit); d++) {
res += dfs(i + 1, limit_low && d == lo, limit_high && d == hi);
}
} else { // 这个数位只能填 s[i-diff]
int x = s[i - diff] - '0';
if (lo <= x && x <= min(hi, limit)) {
res = dfs(i + 1, limit_low && x == lo, limit_high && x == hi);
}
}
if (!limit_low && !limit_high) {
memo[i] = res; // 记忆化 (i,false,false)
}
return res;
};
return dfs(0, true, true);
}
};
作者:灵茶山艾府
链接:https://leetcode.cn/problems/count-the-number-of-powerful-integers/solutions/2595149/shu-wei-dp-shang-xia-jie-mo-ban-fu-ti-da-h6ci/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
作者:灵茶山艾府