Problem: The Number of Good Subsets

You are given an integer array `nums`. We call a subset of `nums` good if its
product can be represented as a product of one or more distinct prime numbers.

* For example, if `nums = [1, 2, 3, 4]`: 
* `[2, 3]`, `[1, 2, 3]`, and `[1, 3]` are good subsets with products `6 = 2*3`, `6 = 2*3`, and `3 = 3` respectively.
* `[1, 4]` and `[4]` are not good subsets with products `4 = 2*2` and `4 = 2*2` respectively.

Return the number of different good subsets in `nums` modulo `109 + 7`.

A subset of `nums` is any array that can be obtained by deleting some
(possibly none or all) elements from `nums`. Two subsets are different if and
only if the chosen indices to delete are different.


Python solution:
import math
import itertools
import bisect
import collections
import string
import heapq
import functools
import sortedcontainers
from typing import List, Dict, Tuple, Iterator

class Solution:
  def numberOfGoodSubsets(self, nums: List[int]) -> int:
    kMod = 1_000_000_007
    primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
    n = 1 << len(primes)
    dp = [1] + [0] * (n - 1)
    count = collections.Counter(nums)

    for num, freq in count.items():
      if num == 1:
        continue
      if any(num % squared == 0 for squared in [4, 9, 25]):
        continue
      numPrimesMask = 0
      for i, prime in enumerate(primes):
        if num % prime == 0:
          numPrimesMask += 1 << i
      for primesMask in range(n):
        if primesMask & numPrimesMask > 0:
          continue
        nextPrimesMask = numPrimesMask | primesMask
        dp[nextPrimesMask] += dp[primesMask] * freq
        dp[nextPrimesMask] %= kMod

    return (1 << count[1]) * sum(dp[1:]) % kMod


Java solution:
class Solution {
  public int numberOfGoodSubsets(int[] nums) {
    final int[] primes = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29};
    final int n = 1 << primes.length;
    final int maxNum = Arrays.stream(nums).max().getAsInt();
    long[] dp = new long[n];
    int[] count = new int[maxNum + 1];

    dp[0] = 1;

    for (final int num : nums)
      ++count[num];

    for (int num = 2; num <= maxNum; ++num) {
      if (count[num] == 0)
        continue;
      if (num % 4 == 0 || num % 9 == 0 || num % 25 == 0)
        continue;
      final int numPrimesMask = getPrimesMask(num, primes);
      for (int primesMask = 0; primesMask < n; ++primesMask) {
        if ((primesMask & numPrimesMask) > 0)
          continue;
        final int nextPrimesMask = primesMask | numPrimesMask;
        dp[nextPrimesMask] += dp[primesMask] * count[num];
        dp[nextPrimesMask] %= MOD;
      }
    }

    return (int) (modPow(2, count[1]) * ((Arrays.stream(dp).sum() - 1) % MOD) % MOD);
  }

  private static final int MOD = 1_000_000_007;

  private int getPrimesMask(int num, int[] primes) {
    int primesMask = 0;
    for (int i = 0; i < primes.length; ++i)
      if (num % primes[i] == 0)
        primesMask |= 1 << i;
    return primesMask;
  }

  private long modPow(long x, long n) {
    if (n == 0)
      return 1;
    if (n % 2 == 1)
      return x * modPow(x, n - 1) % MOD;
    return modPow(x * x % MOD, n / 2);
  }
}


C++ solution:
class Solution {
 public:
  int numberOfGoodSubsets(vector<int>& nums) {
    const vector<int> primes{2, 3, 5, 7, 11, 13, 17, 19, 23, 29};
    const int n = 1 << primes.size();
    const int maxNum = ranges::max(nums);
    vector<long> dp(n);
    vector<int> count(maxNum + 1);

    dp[0] = 1;

    for (const int num : nums)
      ++count[num];

    for (int num = 2; num <= maxNum; ++num) {
      if (count[num] == 0)
        continue;
      if (num % 4 == 0 || num % 9 == 0 || num % 25 == 0)
        continue;
      const int numPrimesMask = getPrimesMask(num, primes);
      for (int primesMask = 0; primesMask < n; ++primesMask) {
        if ((primesMask & numPrimesMask) > 0)
          continue;
        const int nextPrimesMask = primesMask | numPrimesMask;
        dp[nextPrimesMask] += dp[primesMask] * count[num];
        dp[nextPrimesMask] %= kMod;
      }
    }

    return modPow(2, count[1]) *
           (accumulate(dp.begin() + 1, dp.end(), 0L) % kMod) % kMod;
  }

 private:
  static constexpr int kMod = 1'000'000'007;

  int getPrimesMask(int num, const vector<int>& primes) {
    int primesMask = 0;
    for (int i = 0; i < primes.size(); ++i)
      if (num % primes[i] == 0)
        primesMask |= 1 << i;
    return primesMask;
  }

  long modPow(long x, long n) {
    if (n == 0)
      return 1;
    if (n % 2 == 1)
      return x * modPow(x % kMod, (n - 1)) % kMod;
    return modPow(x * x % kMod, (n / 2)) % kMod;
  }
};