LC 6115. 统计理想数组的数目

https://leetcode.cn/contest/weekly-contest-301/problems/count-the-number-of-ideal-arrays/


这题如果直接上DP的话,那么时间复杂度会非常高:假如每个元素平均的因子数量是K的话,那么复杂度就是O(N * maxValue * K). 所以这题肯定需要某种数学解法。

class Solution:
    def idealArrays(self, n: int, maxValue: int) -> int:
        adj = [[] for _ in range(1 + maxValue)]
        for i in range(1, maxValue + 1):
            for j in range(i, maxValue + 1):
                if j % i == 0:
                    adj[i].append(j)

        dp = [[0] * (1 + maxValue) for _ in range(2)]
        for i in range(1 + maxValue):
            dp[0][i] = 1

        now = 0
        MOD = 10 ** 9 + 7
        for _ in range(1, n):
            for i in range(1 + maxValue):
                dp[1 - now][i] = 0
            for i in range(1, maxValue + 1):
                for x in adj[i]:
                    dp[1 - now][x] += dp[now][i]
            now = 1 - now

        ans = sum(dp[now]) % MOD
        return ans


这个解答我觉得非常好 https://leetcode.cn/problems/count-the-number-of-ideal-arrays/solution/shu-lun-zu-he-shu-xue-zuo-fa-by-endlessc-iouh/

假设X可以分解为 `X=(p1 * x1) … (pk * xk)` 的话,我们可以逐个质因子考虑

class Solution:
    def idealArrays(self, n: int, maxValue: int) -> int:
        # 质因子分解
        ks = [[] for _ in range(maxValue + 1)]
        for i in range(2, maxValue + 1):
            k, x = 2, i
            while k * k <= x:
                if x % k == 0:
                    c = 0
                    while x % k == 0:
                        c += 1
                        x //= k
                    ks[i].append(c)
                k += 1
            if x > 1:
                ks[i].append(1)

        MOD = 10 ** 9 + 7

        # 计算出C(n, k)
        import functools
        @functools.lru_cache(maxsize=None)
        def comb(n, k):
            if k == 0: return 1
            if n == k: return 1
            return (comb(n - 1, k - 1) + comb(n - 1, k)) % MOD

        ans = 0
        # 计算结尾为i的可能数
        for i in range(1, maxValue + 1):
            mul = 1
            # 考虑每个质因子分布的可能性
            for k in ks[i]:
                mul = mul * comb(n + k - 1, k)
                mul = mul % MOD
            ans += mul
            ans %= MOD
        return ans