Problem Description
Given two positive integers l and r, count how many numbers in the inclusive range [l, r] are “beautiful”. A number is beautiful if the product of its digits is divisible by the sum of its digits. For example, 10 is beautiful because 1×0 = 0 and 0 is divisible by 1+0 = 1.
Key Insights
- Digits that include zero automatically yield a product of 0 (and as long as the sum is positive, 0 mod (sum) equals 0).
- Every one‐digit number is beautiful since d % d = 0.
- The direct brute force solution is infeasible for r up to 10^9.
- A digit DP approach is viable by iterating over the digits of the number while accumulating both the sum and product of digits.
- To avoid an explosion of state when accumulating the product, a key optimization is to use a flag (“zeroFound”) when a zero is encountered, as then the product becomes 0 and the condition is automatically met.
- The overall answer is computed as countBeautiful(r) – countBeautiful(l – 1).
Space and Time Complexity
Time Complexity: O(digit_count × state_space) where state_space is determined by parameters (current position, tight flag, started flag, zeroFound flag, accumulated sum, and accumulated product). With maximum 10 digits and memoization, the number of unique states remains manageable. Space Complexity: O(number of states) due to memoization, which is feasible given the reduced state space from using flags and the limited number of digits.
Solution
We use a digit dynamic programming (DP) approach to count numbers up to a given limit which satisfy the “beautiful” property. The state in our recursive DP includes: • pos: current digit index in the number’s digit list. • tight: indicates whether the current prefix exactly matches the prefix of the limit (controls whether we can choose any digit or only up to a limit). • started: indicates whether we have begun the number (to handle leading zeros). • zeroFound: a flag to mark if we have already encountered a digit ‘0’ (in which case the product becomes 0). • s: the accumulated sum of digits. • p: the accumulated product of digits (if no zero has been encountered).
When we reach the end of the digits, if a number has been started then: • If zeroFound is true, the product is 0 and the condition holds. • Otherwise, we check if p % s == 0.
We then compute the answer for r and subtract the answer for (l – 1) so that only the numbers in [l, r] are counted.
The implementations in Python, JavaScript, C++ and Java all use this recursive DP (with memoization) approach along with standard digit DP techniques.