Welcome to Subscribe On Youtube

2719. Count of Integers

Description

You are given two numeric strings num1 and num2 and two integers max_sum and min_sum. We denote an integer x to be good if:

  • num1 <= x <= num2
  • min_sum <= digit_sum(x) <= max_sum.

Return the number of good integers. Since the answer may be large, return it modulo 109 + 7.

Note that digit_sum(x) denotes the sum of the digits of x.

 

Example 1:

Input: num1 = "1", num2 = "12", min_sum = 1, max_sum = 8
Output: 11
Explanation: There are 11 integers whose sum of digits lies between 1 and 8 are 1,2,3,4,5,6,7,8,10,11, and 12. Thus, we return 11.

Example 2:

Input: num1 = "1", num2 = "5", min_sum = 1, max_sum = 5
Output: 5
Explanation: The 5 integers whose sum of digits lies between 1 and 5 are 1,2,3,4, and 5. Thus, we return 5.

 

Constraints:

  • 1 <= num1 <= num2 <= 1022
  • 1 <= min_sum <= max_sum <= 400

Solutions

Solution 1: Digit DP

The problem is actually asking for the number of integers in the range $[num1,..num2]$ whose digit sum is in the range $[min_sum,..max_sum]$. For this kind of range $[l,..r]$ problem, we can consider transforming it into finding the answers for $[1,..r]$ and $[1,..l-1]$, and then subtracting the latter from the former.

For the answer to $[1,..r]$, we can use digit DP to solve it. We design a function $dfs(pos, s, limit)$, which represents the number of schemes when we are currently processing the $pos$th digit, the digit sum is $s$, and whether the current number has an upper limit $limit$. Here, $pos$ is enumerated from high to low.

For $dfs(pos, s, limit)$, we can enumerate the value of the current digit $i$, and then recursively calculate $dfs(pos+1, s+i, limit \bigcap i==up)$, where $up$ represents the upper limit of the current digit. If $limit$ is true, then $up$ is the upper limit of the current digit, otherwise $up$ is $9$. If $pos$ is greater than or equal to the length of $num$, then we can judge whether $s$ is in the range $[min_sum,..max_sum]$. If it is, return $1$, otherwise return $0$.

The time complexity is $O(10 \times n \times max_sum)$, and the space complexity is $O(n \times max_sum)$. Here, $n$ represents the length of $num$.

  • import java.math.BigInteger;
    
    class Solution {
        private final int mod = (int) 1e9 + 7;
        private Integer[][] f;
        private String num;
        private int min;
        private int max;
    
        public int count(String num1, String num2, int min_sum, int max_sum) {
            min = min_sum;
            max = max_sum;
            num = num2;
            f = new Integer[23][220];
            int a = dfs(0, 0, true);
            num = new BigInteger(num1).subtract(BigInteger.ONE).toString();
            f = new Integer[23][220];
            int b = dfs(0, 0, true);
            return (a - b + mod) % mod;
        }
    
        private int dfs(int pos, int s, boolean limit) {
            if (pos >= num.length()) {
                return s >= min && s <= max ? 1 : 0;
            }
            if (!limit && f[pos][s] != null) {
                return f[pos][s];
            }
            int ans = 0;
            int up = limit ? num.charAt(pos) - '0' : 9;
            for (int i = 0; i <= up; ++i) {
                ans = (ans + dfs(pos + 1, s + i, limit && i == up)) % mod;
            }
            if (!limit) {
                f[pos][s] = ans;
            }
            return ans;
        }
    }
    
  • class Solution {
    public:
        int count(string num1, string num2, int min_sum, int max_sum) {
            const int mod = 1e9 + 7;
            int f[23][220];
            memset(f, -1, sizeof(f));
            string num = num2;
    
            function<int(int, int, bool)> dfs = [&](int pos, int s, bool limit) -> int {
                if (pos >= num.size()) {
                    return s >= min_sum && s <= max_sum ? 1 : 0;
                }
                if (!limit && f[pos][s] != -1) {
                    return f[pos][s];
                }
                int up = limit ? num[pos] - '0' : 9;
                int ans = 0;
                for (int i = 0; i <= up; ++i) {
                    ans += dfs(pos + 1, s + i, limit && i == up);
                    ans %= mod;
                }
                if (!limit) {
                    f[pos][s] = ans;
                }
                return ans;
            };
    
            int a = dfs(0, 0, true);
            for (int i = num1.size() - 1; ~i; --i) {
                if (num1[i] == '0') {
                    num1[i] = '9';
                } else {
                    num1[i] -= 1;
                    break;
                }
            }
            num = num1;
            memset(f, -1, sizeof(f));
            int b = dfs(0, 0, true);
            return (a - b + mod) % mod;
        }
    };
    
  • class Solution:
        def count(self, num1: str, num2: str, min_sum: int, max_sum: int) -> int:
            @cache
            def dfs(pos: int, s: int, limit: bool) -> int:
                if pos >= len(num):
                    return int(min_sum <= s <= max_sum)
                up = int(num[pos]) if limit else 9
                return (
                    sum(dfs(pos + 1, s + i, limit and i == up) for i in range(up + 1)) % mod
                )
    
            mod = 10**9 + 7
            num = num2
            a = dfs(0, 0, True)
            dfs.cache_clear()
            num = str(int(num1) - 1)
            b = dfs(0, 0, True)
            return (a - b) % mod
    
    
  • func count(num1 string, num2 string, min_sum int, max_sum int) int {
    	const mod = 1e9 + 7
    	f := [23][220]int{}
    	for i := range f {
    		for j := range f[i] {
    			f[i][j] = -1
    		}
    	}
    	num := num2
    	var dfs func(int, int, bool) int
    	dfs = func(pos, s int, limit bool) int {
    		if pos >= len(num) {
    			if s >= min_sum && s <= max_sum {
    				return 1
    			}
    			return 0
    		}
    		if !limit && f[pos][s] != -1 {
    			return f[pos][s]
    		}
    		var ans int
    		up := 9
    		if limit {
    			up = int(num[pos] - '0')
    		}
    		for i := 0; i <= up; i++ {
    			ans = (ans + dfs(pos+1, s+i, limit && i == up)) % mod
    		}
    		if !limit {
    			f[pos][s] = ans
    		}
    		return ans
    	}
    	a := dfs(0, 0, true)
    	t := []byte(num1)
    	for i := len(t) - 1; i >= 0; i-- {
    		if t[i] != '0' {
    			t[i]--
    			break
    		}
    		t[i] = '9'
    	}
    	num = string(t)
    	f = [23][220]int{}
    	for i := range f {
    		for j := range f[i] {
    			f[i][j] = -1
    		}
    	}
    	b := dfs(0, 0, true)
    	return (a - b + mod) % mod
    }
    
  • function count(num1: string, num2: string, min_sum: number, max_sum: number): number {
        const mod = 1e9 + 7;
        const f: number[][] = Array.from({ length: 23 }, () => Array(220).fill(-1));
        let num = num2;
        const dfs = (pos: number, s: number, limit: boolean): number => {
            if (pos >= num.length) {
                return s >= min_sum && s <= max_sum ? 1 : 0;
            }
            if (!limit && f[pos][s] !== -1) {
                return f[pos][s];
            }
            let ans = 0;
            const up = limit ? +num[pos] : 9;
            for (let i = 0; i <= up; i++) {
                ans = (ans + dfs(pos + 1, s + i, limit && i === up)) % mod;
            }
            if (!limit) {
                f[pos][s] = ans;
            }
            return ans;
        };
        const a = dfs(0, 0, true);
        num = (BigInt(num1) - 1n).toString();
        f.forEach(v => v.fill(-1));
        const b = dfs(0, 0, true);
        return (a - b + mod) % mod;
    }
    
    

All Problems

All Solutions