LC 1735. 生成乘积数组的方案数
https://leetcode-cn.com/problems/count-ways-to-make-array-with-product/
这题想要计算的是,将一个数K分解成为N个数,有多少种组合。考虑到n, k <= 10 ** 4, 所以这题用简单的搜索是不行的。
凡是涉及到整数的分解,一定要想到从质数角度进行考虑。假设6 = (2 ** 1) * (3 * 1). 如果要分解成为3个数的话,那么其实变成了两个问题:
- 将2的指数(这里是1)分解成为3个数,有 [0,0,1], [0,1,0], [1,0,0] 三种
- 将3的指数(这里是1)分解成为3个数,和上面一样,有 [0,0,1], [0,1,0], [1,0,0] 三种
每种质数的分法最后乘在一起就是结果,也就是9种。
原问题变为,将一个数X拆分成为N个数,使得这些数的和是X,有多少种方法。如果k <= 10 ** 4 的话,那么X肯定不会超过13。这个问题就是一个典型的动态规划,空间是O(N * X), 时间复杂度是O(N * X * X).
class Solution: def waysToFillArray(self, queries: List[List[int]]) -> List[int]: # import functools # @functools.lru_cache(maxsize = None) # def DP(n, k): # if (k == 0): return 1 # if (n == 1): return 1 # res = 0 # for k1 in range(0, k+1): # res += DP(n-1, k-k1) # return res N = max((x[0] for x in queries)) DP = [[0] * (N+1) for _ in range(20)] DP = [[0] * 20 for _ in range(N+1)] DP[0] = [1] * 20 DP[1] = [1] * 20 for i in range(2, N+1): for k in range(0, 20): ans = 0 for k1 in range(0, k+1): ans += DP[i-1][k-k1] DP[i][k] = ans # print(DP[3][10]) PMS = [0] * 101 for i in range(2, 100): if PMS[i] == 1: continue for j in range(i, 100): if i * j >= 100: break PMS[i * j] = 1 PS = [] for i in range(2, 100): if PMS[i] == 0: PS.append(i) # print(PS) MOD = 10 ** 9 + 7 def test(n, k): ans = 1 for p in PS: if k % p == 0: cnt = 0 while k % p == 0: cnt += 1 k = k // p res = DP[n][cnt] # print(n, p, cnt, res) ans = ans * res if k != 1: ans = ans * DP[n][1] ans = ans % MOD return ans ans = [] for n, k in queries: res = test(n, k) ans.append(res) return ans