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 1Input: 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.
- Start another loop from j = 1 to j*j < i to count perfect squares.
- Return the ans with modulo.
Below is the Implementation of the above approach:
// 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 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) |
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# 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 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.
|
3
Time Complexity: O(1024 * sqrt(X)) where X is largest number in temp
Auxiliary Space: O(210)
Related Articles: