数位动态规划(数位DP)主要用于解决“在区间[L,R]这个范围内,满足某种约束的数字的数量、总和、平方“这一类问题
例如:https://leetcode.cn/problems/count-of-integers/description/
给你两个数字字符串 num1 和 num2 ,以及两个整数 max_sum 和 min_sum 。如果一个整数 x满足以下条件,我们称它是一个好整数: num1 <= x <= num2 min_sum <= digit_sum(x) <= max_sum.
请你返回好整数的数目。答案可能很大,请返回答案对 109 + 7 取余后的结果。
注意,digit_sum(x) 表示 x 各位数字之和。
解题:
class Solution {
int[][] cache;
char[] s;
int min, max;
private static final int MOD = (int) 1e9 + 7;
public int count(String num1, String num2, int min_sum, int max_sum) {
min = min_sum;
max = max_sum;
int cnt = 0;
for (int i = 0; i < num1.length(); i++) {
cnt += num1.charAt(i) - '0';
}
if (min <= cnt && cnt <= max) {
return (count(num2) - count(num1)+MOD+1)%MOD;
}
return (count(num2) - count(num1)+MOD)%MOD;
}
private int count(String num) {
s=num.toCharArray();
cache = new int[num.length()][max+1];
for (int[] ints : cache) {
Arrays.fill(ints, -1);
}
return fun(0, 0, true);
}
//i:第i位 cnt:现在数字的大小 isLimit:是否被限制大小了
public int fun(int i, int cnt, boolean isLimit) {
if (cnt > max) {
return 0;
}
if (i == s.length) {
return min <= cnt ? 1 : 0;
}
if (!isLimit && cache[i][cnt] != -1) {
return cache[i][cnt];
}
int res = 0;
int up = isLimit ? s[i] - '0' : 9;
for (int j = 0; j <= up; j++) {
res = (res+fun(i + 1, cnt + j, isLimit && j == up))%(int)(1e9+7);
}
if (!isLimit) {
cache[i][cnt] = res;
}
return res;
}
}