题目:
给你一个整数数组 nums 。如果 nums 的一个子集中,所有元素的乘积可以表示为一个或多个 互不相同的质数 的乘积,那么我们称它为 好子集 。
比方说,如果 nums = [1, 2, 3, 4] :
[2, 3] ,[1, 2, 3] 和 [1, 3] 是 好 子集,乘积分别为 6 = 23 ,6 = 23 和 3 = 3 。
[1, 4] 和 [4] 不是 好 子集,因为乘积分别为 4 = 22 和 4 = 22 。
请你返回 nums 中不同的 好 子集的数目对 109 + 7 取余 的结果。
nums 中的 子集 是通过删除 nums 中一些(可能一个都不删除,也可能全部都删除)元素后剩余元素组成的数组。如果两个子集删除的下标不同,那么它们被视为不同的子集。
解答:
class Solution:
def numberOfGoodSubsets(self, nums: List[int]) -> int:
#primes:[1,30]中的质数合集
primes=[]
for i in range(2,31):
t=int(pow(i,0.5))+1
flag=True
for j in range(2,t):
if i%j==0:
flag=False
break
if flag:
primes.append(i)
#primes=[2,3,5,7,11,13,17,19,23,29]
mod = 10**9 + 7
freq = Counter(nums)
f = [0] * (1 << len(primes))
f[0] = pow(2, freq[1], mod)
for i, occ in freq.items():
if i == 1:
continue
# 检查 i 的每个质因数是否均不超过 1 个
subset, x = 0, i
check = True
for j, prime in enumerate(primes):
if x % (prime * prime) == 0:
check = False
break
if x % prime == 0:
subset |= (1 << j)
if not check:
continue
# 动态规划
for mask in range((1 << len(primes)) - 1, 0, -1):
if (mask & subset) == subset:
f[mask] = (f[mask] + f[mask ^ subset] * occ) % mod
ans = sum(f[1:]) % mod
return ans