1994. 好子集的数目
给你一个整数数组 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 中一些(可能一个都不删除,也可能全部都删除)元素后剩余元素组成的数组。如果两个子集删除的下标不同,那么它们被视为不同的子集。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/the-number-of-good-subsets
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
import java.util.*;
class Solution {
static final int[] PRIMES = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29};
static final Set CANDIDATES = new HashSet() {{
addAll(Arrays.asList(2, 3, 5, 6, 7, 10, 11, 13, 14, 15, 17, 19, 21, 22, 23, 26, 29, 30));
}};
static final Map MASK = new HashMap() {{
for (int x : CANDIDATES) {
int mask = 0;
for (int i = 0; i < PRIMES.length; ++i) {
if (x % PRIMES[i] == 0) {
mask |= (1 << i);
}
}
put(x, mask);
}
}};
static final int NUM_MAX = 30;
static final int MOD = 1000000007;
public int numberOfGoodSubsets(int[] nums) {
int[] freq = new int[NUM_MAX + 1];
for (int num : nums) {
++freq[num];
}
int[] f = new int[1 << PRIMES.length];
f[0] = 1;
for (int i = 0; i < freq[1]; ++i) {
f[0] = f[0] * 2 % MOD;
}
for (int i = 2; i <= NUM_MAX; ++i) {
if (freq[i] == 0 || !CANDIDATES.contains(i)) {
continue;
}
int subset = MASK.get(i);
for (int mask = (1 << PRIMES.length) - 1; mask > 0; --mask) {
if ((mask & subset) == subset) {
f[mask] = (int) ((f[mask] + ((long) f[mask ^ subset]) * freq[i]) % MOD);
}
}
}
int ans = 0;
for (int mask = 1, maskMax = (1 << PRIMES.length); mask < maskMax; ++mask) {
ans = (ans + f[mask]) % MOD;
}
return ans;
}
}