Open In App

Count Subsets whose product is not divisible by perfect square

Improve
Improve
Like Article
Like
Save
Share
Report

Given an array arr[] (where arr[i] lies in the range [2, 30] )of size N, the task is to find the number of subsets such that the product of the elements is not divisible by any perfect square number.

Examples:

Input: arr[] =  {2, 4, 3}
Output : 3
Explanation: 
Subset1 – {2} 
Subset2 – {3}
Subset3 – {2, 3}  6 is not divisible by any perfect square number greater  than 1  

Input: arr[] = { 2, 2, 2 }
Output: 3
Explanation: 
{2} subset contains an element at index 0
{2} subset contains an element at index 1
{2} subset contains an element at index 2  

Approach: The problem can be solved based on the following idea:

Suppose the product is X. X can be written as X = p1e1 * p2e2 * p3e3 * . . . where pi is a prime number and ei is the exponent for the prime number pi. So we can conclude that all the prime numbers should have exponent 1. Otherwise, X would be divisible by a perfect square.

As the constraint for arr[i] is 30, there are only 10 primes under that {2, 3, 5, 7, 11, 13, 17, 19, 23,  29}. So total 1024 numbers are possible. The task is to find the subsets with product being any of these numbers.

Follow the steps mentioned below to implement the idea:

  • Create a map and store the frequency of all elements of the array.
  • Create an array to store all the prime numbers less than 30.
  • Create a dummy array (say temp[]) and store the numbers that can be made using the primes less than 30.
  • Then initialize a variable ans to store the result.
  • Start a loop and iterate over the temp array.
    • Start another loop from j = 1 to j*j < i to count perfect squares.
      • Inside this loop count the number of subsets that have product as i and increment the answer.
  • Return the ans with modulo.

Below is the Implementation of the above approach:

C++




// C++ code to implement the approach
 
#include <bits/stdc++.h>
using namespace std;
 
long mod = 1000000007;
 
// Function to find the number of subsets
int findNumbers(vector<int>& arr)
{
    int n = arr.size();
 
    // Map to find the frequency
    // of each number in the array
    unordered_map<long, long> mp;
    for (auto i : arr)
        mp[i]++;
 
    // Prime numbers less than 30
    vector<int> prime
        = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29 };
 
    // Vector to store  numbers that can be made
    // using combination of above prime numbers
    vector<int> temp;
 
    for (int i = 1; i < 1024; i++) {
        long p = 1;
        for (int j = 0; j < 11; j++) {
            if ((i >> j) & 1)
                p *= prime[j];
        }
        temp.push_back(p);
    }
 
    int ans = 0;
    for (auto i : temp) {
        for (int j = 1; j * j < i; j++) {
            if (i % j == 0) {
                mp[i]
                    = (mp[i] + mp[j] * mp[i / j]) % mod;
            }
        }
        ans = (ans + mp[i]) % mod;
    }
 
    return ans;
}
 
// Driver Code
int main()
{
    vector<int> arr = { 2, 4, 3 };
 
    // Function call
    int ans = findNumbers(arr);
    cout << ans << endl;
 
    return 0;
}


Java




// Java code to implement the approach
import java.util.*;
 
class GFG {
    static long mod = 1000000007;
 
    static int findNumbers(List<Integer> arr)
    {
        int n = arr.size();
 
        // Map to find the frequency
        // of each number in the array
        HashMap<Long, Long> mp = new HashMap<Long, Long>();
        for (int i : arr) {
            if (mp.containsKey((long)i))
                mp.put((long)i, mp.get((long)i) + 1);
            else
                mp.put((long)i, (long)1);
        }
 
        // Prime numbers less than 30
        List<Integer> prime = Arrays.asList(
            2, 3, 5, 7, 11, 13, 17, 19, 23, 29);
 
        // List to store numbers that can be made
        // using combination of above prime numbers
        List<Integer> temp = new ArrayList<Integer>();
 
        for (int i = 1; i < 1024; i++) {
            long p = 1;
            for (int j = 0; j < 11; j++) {
                if ((i >> j) % 2 == 1)
                    p *= prime.get(j);
            }
            temp.add((int)p);
        }
 
        int ans = 0;
        for (int i : temp) {
            for (int j = 1; j * j < i; j++) {
                if (i % j == 0) {
                    if (mp.containsKey((long)j)
                        && mp.containsKey((long)(i / j))) {
                        if (mp.containsKey((long)i))
                            mp.put((long)i,
                                   (mp.get((long)i)
                                    + mp.get((long)j)
                                          * mp.get((
                                              long)(i / j)))
                                       % mod);
                        else
                            mp.put((long)i,
                                   (mp.get((long)j)
                                    * mp.get((long)(i / j)))
                                       % mod);
                    }
                }
            }
            if (mp.containsKey((long)i))
                ans = (ans + (int)(mp.get((long)i) % mod))
                      % (int)mod;
        }
 
        return ans;
    }
 
    public static void main(String[] args)
    {
        List<Integer> arr = Arrays.asList(2, 4, 3);
 
        // Function call
        int ans = findNumbers(arr);
        System.out.println(ans);
    }
}
// This code is contributed by Prasad Kandekar(prasad264)


Python3




import collections
 
def findNumbers(arr):
    n = len(arr)
    mp = collections.defaultdict(int)
    for i in arr:
        mp[i] += 1
 
    prime = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
 
    temp = []
    for i in range(1, 1024):
        p = 1
        for j in range(11):
            if (i >> j) & 1:
                p *= prime[j]
        temp.append(p)
 
    mod = 1000000007
    ans = 0
    for i in temp:
        for j in range(1, int(i ** 0.5) + 1):
            if i % j == 0 and j in mp:
                mp[i] = (mp[i] + mp[j] * mp[i // j]) % mod
        ans = (ans + mp[i]) % mod
         
    return ans
 
arr = [2, 4, 3]
ans = findNumbers(arr)
print(ans)


C#




// C# code to implement the approach
using System;
using System.Collections.Generic;
using System.Linq;
 
class Solution
{
    static long mod = 1000000007;
 
    static int findNumbers(List<int> arr)
    {
        int n = arr.Count();
 
        // Map to find the frequency
        // of each number in the array
        Dictionary<long, long> mp = new Dictionary<long, long>();
        foreach (var i in arr)
        {
            if (mp.ContainsKey(i))
                mp[i]++;
            else
                mp[i] = 1;
        }
 
        // Prime numbers less than 30
        List<int> prime = new List<int> { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29 };
 
        // Vector to store numbers that can be made
        // using combination of above prime numbers
        List<int> temp = new List<int>();
 
        for (int i = 1; i < 1024; i++)
        {
            long p = 1;
            for (int j = 0; j < 11; j++)
            {
                if ((i >> j) % 2 == 1)
                    p *= prime[j];
            }
            temp.Add((int)p);
        }
 
        int ans = 0;
        foreach (var i in temp)
        {
            for (int j = 1; j * j < i; j++)
            {
                if (i % j == 0)
                {
                    if (mp.ContainsKey(j) && mp.ContainsKey(i / j))
                    {
                        if(mp.ContainsKey(i))
                        mp[i] = (mp[i] + mp[j] * mp[i / j]) % mod;
                        else
                        mp[i] = (mp[j] * mp[i / j]) % mod;
                    }
                     
                }
            }
            if(mp.ContainsKey(i))
            ans = (ans + (int)mp[i]) % (int)mod;
        }
 
        return ans;
    }
 
    public static void Main()
    {
        List<int> arr = new List<int> { 2, 4, 3 };
 
        // Function call
        int ans = findNumbers(arr);
        Console.WriteLine(ans);
    }
}
 
// This code is contributed by Utkarsh Kumar.


Javascript




// JavaScript code for the above approach
        let mod = 1000000007;
 
        // Function to find the number of subsets
        function findNumbers(arr) {
            let n = arr.length;
 
            // Map to find the frequency
            // of each number in the array
            let mp = new Map();
            for (let i of arr) {
                if (mp.has(i)) {
                    mp.set(i, mp.get(i) + 1)
                }
                else {
                    mp.set(i, 1);
                }
            }
            
 
            // Prime numbers less than 30
            let prime
                = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29];
 
            // vector to store  numbers that can be made
            // using combination of above prime numbers
            let temp = [];
 
            for (let i = 1; i < 1024; i++) {
                let p = 1;
                for (let j = 0; j < 11; j++) {
                    if ((i >> j) & 1)
                        p *= prime[j];
                }
                temp.push(p);
            }
 
            let ans = 1;
            for (let i of temp) {
 
                for (let j = 1; j * j < i; j++) {
                    if (i % j == 0) {
 
                        if (mp.has(i) && mp.has(j) && mp.has(i / j))
                            mp.set(i, (mp.get(i) + mp.get(j) * mp.get(Math.floor(i / j))) % mod);
                    }
                }
                if (mp.has(i))
                    ans = (ans % mod + mp.get(i) % mod) % mod;
            }
            
 
            return ans;
        }
 
        // Driver Code
 
        let arr = [2, 4, 3];
 
        // Function call
        let ans = findNumbers(arr);
        console.log(ans)
         
        // This code is contributed by poojaagarwals2.


Output

3

Time Complexity:  O(1024 * sqrt(X))  where X is largest number in temp
Auxiliary Space: O(210)

Related Articles:



Last Updated : 22 Feb, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads