LC 8013. 范围中美丽整数的数目

https://leetcode.cn/problems/number-of-beautiful-integers-in-the-range/description/

这次算是自己琢磨出来怎么写数位dp的,实现中有两个点,分别都是和isStart有关系的:

  1. 只有isStart=False,的时候,才可以继续以isStart=False递归下去,否则就要开始枚举具体数字了。
  2. 只有isStart=True的时候,才能枚举left被用于odd/even. 如果isStart=False,那么只能粗略判断(odd + left) < even

然后就是这个状态中value必须取模k, 否则这个状态数量就太大了。

class Solution:
    def numberOfBeautifulIntegers(self, low: int, high: int, k: int) -> int:
        def OkOddEven(isStart, odd, even, left):
            if isStart:
                for x in range(0, left + 1):
                    if (odd + x) == (even + left - x):
                        return True
                return False
            else:
                if (odd + left) < even or (even + left) < odd:
                    return False
                return True

        def search(ss):
            import functools
            @functools.cache
            def f(i, isLimit, isStart, odd, even, value):
                # print(i, isLimit, isStart, odd, even, value)
                if i == len(ss):
                    if not isStart: return 0
                    if odd == even and value % k == 0:
                        # print(value)
                        return 1
                    return 0

                left = len(ss) - i
                if not OkOddEven(isStart, odd, even, left):
                    return 0

                ans = 0
                if not isStart:
                    ans += f(i + 1, True, False, odd, even, value)

                from_value = 1 if not isStart else 0
                to_value = int(ss[i]) if not isLimit else 9
                for x in range(from_value, to_value + 1):
                    ans += f(i + 1, isLimit or x < int(ss[i]), isStart or x != 0,
                             odd + (x % 2), even + (x + 1) % 2,
                             # value * 10 + x)
                             (value * 10 + x) % k)
                return ans

            return f(0, False, False, 0, 0, 0)

        h = search(str(high))
        l = search(str(low - 1))
        ans = h - l
        return ans