Open In App

Counting Subsets with prime product property

Last Updated : 17 Aug, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given an array arr[] of size N. The task is to find a number of subsets whose product can be represented as a product of one or more distinct prime numbers. Modify your answer to the modulo of 109 + 7.

Example:

Input: N = 4, arr[] = {1, 2, 3, 4}
Output: 6
Explanation: The good subsets are:

  • [1, 2]: product is 2, which is the product of distinct prime 2.
  • [1, 2, 3]: product is 6, which is the product of distinct primes 2 and 3.
  • [1, 3]: product is 3, which is the product of distinct prime 3.
  • [2]: product is 2, which is the product of distinct prime 2.
  • [2, 3]: product is 6, which is the product of distinct primes 2 and 3.
  • [3]: product is 3, which is the product of distinct prime 3.

Input: N = 3, arr[] =  {2, 2, 3}
Output: 5
Explanation: The good subsets are : {2}, {2}, {2, 3}, {2, 3}, {3}

Approach: This can be solved with the following idea: 

The general approach for the given problem is to use dynamic programming to count the number of good subsets.

Below are the steps involved in the implementation of the code:

  • Create a static array map with a size of 31, along with a constant mod of 109 + 7.
  • Find the prime factors of each integer i from 2 to 30 and set the associated bits in map[i] if i is not a multiple of 4 or 9 or equal to 25.
  • Set the first member of the integer array dp to 1 and initialize the integer variables one and cnt to have sizes of 1024 and 31, respectively  Step 4: If the appropriate map[i] value is non-zero and the integer i is not 1, increment one for each integer i in the provided array arr; otherwise, increment the count of i in the cnt array.
  • For each index, i in the cnt array where the value is non-zero, iterate through all the possible subsets of prime numbers using a nested loop over all the possible j values from 0 to 1023. If the jth bit is set and the map[i]th bit is also set, skip to the next j. Otherwise, update the dp[j| map[i]] value with the sum of its current value and the product of the count of i and the dp[j] value.
  • After the loops are complete, initialize a long variable res as 0, iterate through all the elements of the dp array, and update the res value as the sum of its current value and the current element’s value. Then decrement res by 1.
  • If the one value is non-zero, calculate its power using a helper function pow and multiply the result with res. Finally, return the result as an i integer.

Below is the code implementation of the above method:

C++




// C++ code of the above approach
#include <bits/stdc++.h>
using namespace std;
#define mod 1000000007
 
int map_[31];
 
// Function to calculate power
long long pow(int n)
{
    long long res = 1, m = 2;
    while (n != 0) {
        if ((n & 1) == 1)
            res = (res * m) % mod;
        m = m * m % mod;
        n >>= 1;
    }
    return res;
}
 
// Check for prime value
void check_prime_val()
{
    int prime[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29 };
    for (int i = 2; i <= 30; ++i) {
        // If num is a multiple of
        // 4/9/25, adding it to any
        // subset will make it bad
        if (i % 4 == 0 || i % 9 == 0 || i == 25)
            continue;
        int mask = 0;
        for (int j = 0; j < 10; ++j) {
            if (i % prime[j] == 0)
                mask |= 1 << j;
        }
        map_[i] = mask;
    }
}
 
int goodSubsets(int arr[], int n)
{
    int one = 0;
    // dp[set_of_primes] represents
    // the number of times set_of_primes
    // can be formed (set_of_primes ===
    // mask) Since there are 10 possible
    // prime numbers, there are 2^10
    // possible set_of_primes
    int dp[1024] = { 0 }, cnt[31] = { 0 };
    dp[0] = 1;
    for (int i = 0; i < n; i++) {
        if (arr[i] == 1)
            one++;
        else if (map_[arr[i]] != 0)
            cnt[arr[i]]++;
    }
    for (int i = 0; i < 31; ++i) {
        if (cnt[i] == 0)
            continue;
        for (int j = 0; j < 1024; ++j) {
            if ((j & map_[i]) != 0)
                continue;
            dp[j | map_[i]]
                = (dp[j | map_[i]] + dp[j] * cnt[i]) % mod;
        }
    }
    long res = 0;
    for (int i : dp)
        res = (res + i) % mod;
    res--;
    if (one != 0)
        res = res * pow(one) % mod;
    return res;
}
// Driver code
int main()
{
    int arr[] = { 1, 2, 3, 4 };
    int n = sizeof(arr) / sizeof(arr[0]);
 
    check_prime_val();
    // Function call
    cout << goodSubsets(arr, n) << endl;
 
    return 0;
}
// This code is contributed by Tapesh(tapeshdua420)


Java




// Java code of the above approach
class Solution {
 
    static int mod = (int)1e9 + 7;
 
    static int[] map = new int[31];
 
    // Check for prime value
    static
    {
        int[] prime = new int[] { 2, 3, 5, 7, 11,
                                  13, 17, 19, 23, 29 };
        for (int i = 2; i <= 30; ++i) {
 
            // If num is a multiple of
            // 4/9/25, adding it to any
            // subset will make it bad
            if (0 == i % 4 || 0 == i % 9 || 25 == i)
                continue;
            int mask = 0;
            for (int j = 0; j < 10; ++j) {
                if (0 == i % prime[j])
                    mask |= 1 << j;
            }
            map[i] = mask;
        }
    }
 
    public int goodSubsets(int[] arr, int n)
    {
 
        int one = 0;
 
        // dp[set_of_primes] represents
        // the number of times set_of_primes
        // can be formed (set_of_primes ===
        // mask) Since there are 10 possible
        // prime numbers, there are 2^10
        // possible set_of_primes
        int[] dp = new int[1024], cnt = new int[31];
        dp[0] = 1;
        for (int i : arr) {
            if (i == 1)
                one++;
            else if (map[i] != 0)
                cnt[i]++;
        }
        for (int i = 0; i < 31; ++i) {
            if (cnt[i] == 0)
                continue;
            for (int j = 0; j < 1024; ++j) {
                if (0 != (j & map[i]))
                    continue;
                dp[j | map[i]]
                    = (int)((dp[j | map[i]]
                             + dp[j] * (long)cnt[i])
                            % mod);
            }
        }
        long res = 0;
        for (int i : dp)
            res = (res + i) % mod;
        res--;
        if (one != 0)
            res = res * pow(one) % mod;
        return (int)res;
    }
 
    // Function to calculate power
    public long pow(int n)
    {
        long res = 1, m = 2;
        while (n != 0) {
            if (1 == (n & 1))
                res = (res * m) % mod;
            m = m * m % mod;
            n >>= 1;
        }
        return res;
    }
 
    // Driver code
    public static void main(String[] args)
    {
        int[] arr = { 1, 2, 3, 4 };
        int n = arr.length;
        Solution solution = new Solution();
 
        // Function call
        int result = solution.goodSubsets(arr, n);
 
        System.out.println(result);
    }
}


Python3




# Python3 code of the above approach
from typing import List
 
 
class Solution:
    mod = int(1e9 + 7)
    map = [0] * 31
 
    # Check for prime value
    @staticmethod
    def calculatePrimes():
        prime = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
        for i in range(2, 31):
            if i % 4 == 0 or i % 9 == 0 or i == 25:
                continue
            mask = 0
            for j in range(10):
                if i % prime[j] == 0:
                    mask |= (1 << j)
            Solution.map[i] = mask
 
    def goodSubsets(self, arr: List[int], n: int) -> int:
        one = 0
        dp = [0] * 1024
        cnt = [0] * 31
        dp[0] = 1
 
        for i in arr:
            if i == 1:
                one += 1
            elif Solution.map[i] != 0:
                cnt[i] += 1
 
        for i in range(31):
            if cnt[i] == 0:
                continue
            for j in range(1024):
                if j & Solution.map[i]:
                    continue
                dp[j | Solution.map[i]] = (
                    dp[j | Solution.map[i]] + dp[j] * cnt[i]) % Solution.mod
 
        res = 0
        for i in dp:
            res = (res + i) % Solution.mod
        res -= 1
 
        if one != 0:
            pow_val = 1
            m = 2
            while one != 0:
                if one & 1:
                    pow_val = (pow_val * m) % Solution.mod
                m = (m * m) % Solution.mod
                one >>= 1
            res = (res * pow_val) % Solution.mod
 
        return int(res)
 
    # Driver code
    def main(self):
        arr = [1, 2, 3, 4]
        n = len(arr)
 
        # Calculate primes
        Solution.calculatePrimes()
 
        # Create an instance of the class
        solution = Solution()
 
        # Function call
        result = solution.goodSubsets(arr, n)
 
        print(result)
 
 
# Create an instance of the Solution class
solution = Solution()
 
# Call the main function
solution.main()
 
# This code is contributed by shivamgupta0987654321


C#




// c# code for above approach
using System;
 
class Program {
    const int mod = 1000000007;
 
    static int[] map_ = new int[31];
 
    // Function to calculate power
    static long Pow(int n)
    {
        long res = 1;
        long m = 2;
        while (n != 0) {
            if ((n & 1) == 1)
                res = (res * m) % mod;
            m = (m * m) % mod;
            n >>= 1;
        }
        return res;
    }
 
    // Check for prime value
    static void CheckPrimeVal()
    {
        int[] prime
            = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29 };
        for (int i = 2; i <= 30; ++i) {
            // If num is a multiple of
            // 4/9/25, adding it to any
            // subset will make it bad
            if (i % 4 == 0 || i % 9 == 0 || i == 25)
                continue;
            int mask = 0;
            for (int j = 0; j < 10; ++j) {
                if (i % prime[j] == 0)
                    mask |= 1 << j;
            }
            map_[i] = mask;
        }
    }
 
    static int GoodSubsets(int[] arr, int n)
    {
        int one = 0;
        // dp[set_of_primes] represents
        // the number of times set_of_primes
        // can be formed (set_of_primes ===
        // mask) Since there are 10 possible
        // prime numbers, there are 2^10
        // possible set_of_primes
        int[] dp = new int[1024];
        int[] cnt = new int[31];
        dp[0] = 1;
        for (int i = 0; i < n; i++) {
            if (arr[i] == 1)
                one++;
            else if (map_[arr[i]] != 0)
                cnt[arr[i]]++;
        }
        for (int i = 0; i < 31; ++i) {
            if (cnt[i] == 0)
                continue;
            for (int j = 0; j < 1024; ++j) {
                if ((j & map_[i]) != 0)
                    continue;
                dp[j | map_[i]]
                    = (dp[j | map_[i]] + dp[j] * cnt[i])
                      % mod;
            }
        }
        long res = 0;
        foreach(int i in dp) res = (res + i) % mod;
        res--;
        if (one != 0)
            res = (res * Pow(one)) % mod;
        return (int)res;
    }
 
    // Driver code
    static void Main(string[] args)
    {
        int[] arr = { 1, 2, 3, 4 };
        int n = arr.Length;
 
        CheckPrimeVal();
        // Function call
        Console.WriteLine(GoodSubsets(arr, n));
    }
}


Javascript




const mod = 1000000007;
const map_ = new Array(31).fill(0);
 
// Function to calculate power
function pow(n) {
  let res = 1;
  let m = 2;
  while (n !== 0) {
    if ((n & 1) === 1) {
      res = (res * m) % mod;
    }
    m = (m * m) % mod;
    n >>= 1;
  }
  return res;
}
 
// Check for prime value
function check_prime_val() {
  const prime = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29];
  for (let i = 2; i <= 30; ++i) {
   
      // If num is a multiple of
    // 4/9/25, adding it to any
   // subset will make it bad
    if (i % 4 === 0 || i % 9 === 0 || i === 25) {
      continue;
    }
    let mask = 0;
    for (let j = 0; j < 10; ++j) {
      if (i % prime[j] === 0) {
        mask |= 1 << j;
      }
    }
    map_[i] = mask;
  }
}
 
function goodSubsets(arr, n) {
  let one = 0;
   
  // dp[set_of_primes] represents
  // the number of times set_of_primes
  // can be formed (set_of_primes ===
  // mask) Since there are 10 possible
  // prime numbers, there are 2^10
  // possible set_of_primes
  const dp = new Array(1024).fill(0);
  const cnt = new Array(31).fill(0);
  dp[0] = 1;
  for (let i = 0; i < n; i++) {
    if (arr[i] === 1) {
      one++;
    } else if (map_[arr[i]] !== 0) {
      cnt[arr[i]]++;
    }
  }
  for (let i = 0; i < 31; ++i) {
    if (cnt[i] === 0) {
      continue;
    }
    for (let j = 0; j < 1024; ++j) {
      if ((j & map_[i]) !== 0) {
        continue;
      }
      dp[j | map_[i]] = (dp[j | map_[i]] + dp[j] * cnt[i]) % mod;
    }
  }
  let res = 0;
  for (let i of dp) {
    res = (res + i) % mod;
  }
  res--;
  if (one !== 0) {
    res = (res * pow(one)) % mod;
  }
  return res;
}
 
// Driver code
const arr = [1, 2, 3, 4];
const n = arr.length;
check_prime_val();
 
console.log(goodSubsets(arr, n));


Output

6







Time Complexity: O(N*logN)
Auxiliary Space: O(N)



Similar Reads

Count numbers in a given range having prime and non-prime digits at prime and non-prime positions respectively
Given two integers L and R, the task is to find the count of numbers in the range [L, R] having prime digits at prime positions and non-prime digits at non-prime positions. Examples: Input: L = 5, R = 22 Output: 7Explanation: The numbers 6, 8, 9, 12, 13, 15, and 17 have prime digits at prime positions and non-prime digits at non-prime positions. In
15 min read
Maximum number of subsets an array can be split into such that product of their minimums with size of subsets is at least K
Given an array arr[] consisting of N integers and an integer K, the task is to find the maximum number of disjoint subsets that the given array can be split into such that the product of the minimum element of each subset with the size of the subset is at least K. Examples: Input: arr[] = {7, 11, 2, 9, 5}, K = 10Output: 2Explanation:All such disjoi
8 min read
Find prime factors of Z such that Z is product of all even numbers till N that are product of two distinct prime numbers
Given a number N (N &gt; 6), the task is to print the prime factorization of a number Z, where Z is the product of all numbers ≤ N that are even and can be expressed as the product of two distinct prime numbers. Example: Input: N = 6Output: 2→1 3→1Explanation: 6 is the only number ≤ N, which is even and a product of two distinct prime numbers (2 an
7 min read
Partition an array of non-negative integers into two subsets such that average of both the subsets is equal
Given an array of size N. The task is to partition the given array into two subsets such that the average of all the elements in both subsets is equal. If no such partition exists print -1. Otherwise, print the partitions. If multiple solutions exist, print the solution where the length of the first subset is minimum. If there is still a tie then p
14 min read
Sum of subsets of all the subsets of an array | O(3^N)
Given an array arr[] of length N, the task is to find the overall sum of subsets of all the subsets of the array.Examples: Input: arr[] = {1, 1} Output: 6 All possible subsets: a) {} : 0 All the possible subsets of this subset will be {}, Sum = 0 b) {1} : 1 All the possible subsets of this subset will be {} and {1}, Sum = 0 + 1 = 1 c) {1} : 1 All t
6 min read
Sum of subsets of all the subsets of an array | O(2^N)
Given an array arr[] of length N, the task is to find the overall sum of subsets of all the subsets of the array.Examples: Input: arr[] = {1, 1} Output: 6 All possible subsets: a) {} : 0 All the possible subsets of this subset will be {}, Sum = 0 b) {1} : 1 All the possible subsets of this subset will be {} and {1}, Sum = 0 + 1 = 1 c) {1} : 1 All t
6 min read
Divide array in two Subsets such that sum of square of sum of both subsets is maximum
Given an integer array arr[], the task is to divide this array into two non-empty subsets such that the sum of the square of the sum of both the subsets is maximum and sizes of both the subsets must not differ by more than 1.Examples: Input: arr[] = {1, 2, 3} Output: 26 Explanation: Sum of Subset Pairs are as follows (1)2 + (2 + 3)2 = 26 (2)2 + (1
6 min read
Split array into minimum number of subsets such that elements of all pairs are present in different subsets at least once
Given an array arr[] consisting of N distinct integers, the task is to find the minimum number of times the array needs to be split into two subsets such that elements of each pair are present into two different subsets at least once. Examples: Input: arr[] = { 3, 4, 2, 1, 5 } Output: 3 Explanation: Possible pairs are { (1, 2), (1, 3), (1, 4), (1,
6 min read
Sum of subsets of all the subsets of an array | O(N)
Given an array arr[] of length N, the task is to find the overall sum of subsets of all the subsets of the array.Examples: Input: arr[] = {1, 1} Output: 6 All possible subsets: a) {} : 0 All the possible subsets of this subset will be {}, Sum = 0 b) {1} : 1 All the possible subsets of this subset will be {} and {1}, Sum = 0 + 1 = 1 c) {1} : 1 All t
7 min read
Counting pairs with prime bitwise AND in a Singly Linked List
Given a Singly linked list of integers, the task is to count the number of pairs of nodes whose bitwise AND is a prime number. Examples: Input: 4 -&gt; 2 -&gt; 3 -&gt; 1 -&gt; 5 -&gt; 6Output: 3Explanation: The only pair with bitwise AND being a prime number is (2, 3), (2, 6), (3, 6). Input: 10 -&gt; 3 -&gt; 5 -&gt; 7 -&gt; 2 -&gt; 15Output: 11Expl
6 min read