给你两个数字字符串
num1
和num2
,以及两个整数max_sum
和min_sum
。如果一个整数x
满足以下条件,我们称它是一个好整数:
num1 <= x <= num2
min_sum <= digit_sum(x) <= max_sum
.请你返回好整数的数目。答案可能很大,请返回答案对
109 + 7
取余后的结果。注意,
digit_sum(x)
表示x
各位数字之和。
典型数位dp题目,假设 表示 到 间,满足 的数字个数,那么答案就是 。
套用灵神的模板即可。www.bilibili.com/video/BV1rS…
class Solution {
private static final int MOD = 1000000007;
public int count(String num1, String num2, int minSum, int maxSum) {
int ans = calc(num2, minSum, maxSum) - calc(num1, minSum, maxSum) + MOD;
int sum = 0;
for(char c : num1.toCharArray()) {
sum += c - '0';
}
if(minSum <= sum && sum <= maxSum) {
ans++;
}
return ans % MOD;
}
private int calc(String s, int minSum, int maxSum) {
int n = s.length();
int[][] memo = new int[n][Math.min(9 * n, maxSum) + 1];
char[] ch = s.toCharArray();
for(int[] row : memo) {
Arrays.fill(row, -1);
}
return dfs(0, 0, true, ch, minSum, maxSum, memo);
}
private int dfs(int i, int sum, boolean isLimit, char[] s, int minSum, int maxSum, int[][] memo) {
if(sum > maxSum) return 0;
if(i == s.length) return sum >= minSum ? 1 : 0;
if(!isLimit && memo[i][sum] != -1) return memo[i][sum];
int res = 0;
for(int d = 0, up = isLimit ? s[i] - '0' : 9; d <= up; d++) {
res = (res + dfs(i + 1, sum + d, isLimit && (d == up), s, minSum, maxSum, memo)) % MOD;
}
if(!isLimit) memo[i][sum] = res;
return res;
}
}