The Number of Good Subsets

Count subsets whose product is a product of distinct primes — bitmask DP over the 10 primes ≤ 30.

Hard
Time O(n + 30 * 2^10) Space O(2^10)
LeetCode
9 min read
dp bitmask

Problem#

Numbers in [1, 30]. Count non-empty subsets where the product can be expressed as a product of distinct primes. Mod 10⁹+7.

Examples#

  • [1,2,3,4]6

Constraints#

  • 1 <= n <= 10^5.

Hints#

Hint 1
Primes ≤ 30 are 2,3,5,7,11,13,17,19,23,29 (10 primes). Each number ≤ 30 is either invalid (has a squared prime factor) or maps to a subset of those 10. 1 is special — multiplies the count by 2^cnt[1].

Approach#

Bitmask DP over the 10 primes. For each v in [2..30] that’s squarefree, get its prime mask. dp[mask] = number of subset selections whose union mask is mask. Update: for each value’s count, for each existing dp entry with no overlap, multiply and add. Final: sum dp over non-zero masks, multiply by 2^cnt[1].

Solution#

Number of Good Subsets
class Solution {
public:
int numberOfGoodSubsets(vector<int>& nums) {
const int MOD = 1'000'000'007;
vector<int> primes = {2,3,5,7,11,13,17,19,23,29};
vector<int> mask(31, 0);
for (int v = 2; v <= 30; ++v) {
int m = 0, x = v;
bool ok = true;
for (int i = 0; i < 10; ++i) {
int p = primes[i];
if (x % p == 0) {
if ((x / p) % p == 0) { ok = false; break; } // p^2
m |= 1 << i;
x /= p;
}
}
if (ok && x == 1) mask[v] = m;
else mask[v] = -1;
}
vector<int> cnt(31, 0);
for (int v : nums) ++cnt[v];
vector<long long> dp(1 << 10, 0);
dp[0] = 1;
for (int v = 2; v <= 30; ++v) {
if (mask[v] <= 0 || cnt[v] == 0) continue;
int m = mask[v];
long long c = cnt[v];
vector<long long> nd = dp;
for (int s = 0; s < (1 << 10); ++s) {
if (dp[s] && (s & m) == 0) {
nd[s | m] = (nd[s | m] + dp[s] * c) % MOD;
}
}
dp = nd;
}
long long ans = 0;
for (int s = 1; s < (1 << 10); ++s) ans = (ans + dp[s]) % MOD;
long long pow2 = 1;
for (int i = 0; i < cnt[1]; ++i) pow2 = pow2 * 2 % MOD;
return (int)(ans * pow2 % MOD);
}
};

Editorial#

Each value 2..30 maps to a 10-bit prime-mask if squarefree. Subset products are squarefree iff the chosen masks are pairwise disjoint — bitmask DP exactly captures that. 1s freely double the count.

Complexity#

  • Time: O(n + 30 × 2^10).
  • Space: O(2^10).

Concept revision#

Search ESC

Keyboard shortcuts

Shortcuts are disabled while typing in inputs.