好子集的数目
难度:
标签:
题目描述
代码结果
运行时间: 120 ms, 内存: 21.2 MB
/*
* This solution uses Java Streams to process the input array and compute the number of good subsets.
* We use a HashMap to store the frequency of each number and filter those that can form a valid product of distinct primes.
* The implementation also handles numbers with repeated prime factors that cannot form good subsets.
*/
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class GoodSubsetsStream {
private static final int MOD = 1000000007;
private static final int[] PRIMES = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29};
public int numberOfGoodSubsets(int[] nums) {
Map<Integer, Long> freq = Arrays.stream(nums)
.boxed()
.collect(Collectors.groupingBy(n -> n, Collectors.counting()));
long[] dp = new long[1 << PRIMES.length];
dp[0] = 1; // empty set
freq.entrySet().stream()
.filter(entry -> entry.getKey() > 1)
.forEach(entry -> {
int num = entry.getKey();
long count = entry.getValue();
int subsetMask = getPrimeMask(num);
if (subsetMask != -1) {
IntStream.iterate((1 << PRIMES.length) - 1, i -> i >= 0, i -> i - 1)
.filter(state -> (state & subsetMask) == 0)
.forEach(state -> dp[state | subsetMask] = (dp[state | subsetMask] + dp[state] * count) % MOD);
}
});
long result = IntStream.range(1, dp.length).mapToLong(i -> dp[i]).sum() % MOD;
long countOfOnes = freq.getOrDefault(1, 0L);
if (countOfOnes > 0) {
result = (result * powMod(2, countOfOnes)) % MOD;
}
return (int) result;
}
private int getPrimeMask(int num) {
int mask = 0;
for (int i = 0; i < PRIMES.length; i++) {
int prime = PRIMES[i];
if (num % (prime * prime) == 0) return -1;
if (num % prime == 0) mask |= (1 << i);
}
return mask;
}
private long powMod(long base, long exp) {
long result = 1;
while (exp > 0) {
if (exp % 2 == 1) result = (result * base) % MOD;
base = (base * base) % MOD;
exp /= 2;
}
return result;
}
}
解释
方法:
此题解通过考虑不同类型的子集并分情况处理来计算好子集的数目。主要分为三类情况:1.只包含质数的子集;2.包含一个合数的子集;3.包含两个合数的子集。对于每种情况,分别计算可能的子集数量并求和。此外,1的存在对子集的组合方式有特殊影响,因为任何数量的1都可以添加到子集中而不改变乘积的质数组成,因此最后的结果需要乘上2的1的个数次幂。
时间复杂度:
O(1)
空间复杂度:
O(1)
代码细节讲解
🦆
在解决这个问题时,你是如何确定哪些数字是质数,哪些是合数?
▷🦆
为什么需要特别处理数字1,它在计算好子集中起到了什么作用?
▷🦆
解题中提到的情况2和情况3涉及包含一个合数和两个合数的子集,这些子集是如何被计算的?能否详细解释一下函数`ct`和`cth`的具体作用?
▷🦆
最终结果使用了模运算`(10**9+7)`,为什么选择这个数作为模数?
▷