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