Count subsets consisting of each element as a factor of the next element in that subset
Last Updated :
14 Feb, 2023
Given an array arr[] of size N, the task is to find the number of non-empty subsets present in the array such that every element( except the last) in the subset is a factor of the next adjacent element present in that subset. The elements in a subset can be rearranged, therefore, if any rearrangement of a subset satisfies the condition, then that subset will be counted in. However, this subset should be counted in only once.
Examples:
Input: arr[] = {2, 3, 6, 8}
Output: 7
Explanation:
The required subsets are: {2}, {3}, {6}, {8}, {2, 6}, {8, 2}, {3, 6}.
Since subsets {2}, {3}, {6}, {8} contains a single number, they are included in the answer.
In the subset {2, 6}, 2 is a factor of 6.
In the subset {3, 6}, 3 is a factor of 6.
{8, 2} when rearranged into {2, 8}, satisfies the required condition.
Input: arr[] = {16, 18, 6, 7, 2, 19, 20, 9}
Output: 15
Naive Approach: The simplest idea is to generate all possible subsets of the array and print the count of those subsets whose adjacent element (arr[i], arr[i + 1]), arr[i] is a factor of arr[i + 1].
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
#define mod 1000000007
using namespace std;
set< int > getSubset( int n, int * arr,
int mask)
{
set< int > subset;
for ( int i = 0; i < n; i++) {
int b = (mask & (1 << i));
if (b != 0) {
subset.insert(arr[i]);
}
}
return subset;
}
int countSets( int n, set< int >* power_set)
{
int count = 0;
for ( int i = 1; i < (1 << n); i++) {
bool flag = true ;
int N = power_set[i].size();
int * temp = new int [N];
auto it = power_set[i].begin();
for ( int j = 0;
it != power_set[i].end();
j++, it++) {
temp[j] = *it;
}
for ( int k1 = 1, k0 = 0; k1 < N;) {
if (temp[k1] % temp[k0] != 0) {
flag = false ;
break ;
}
if (k0 > 0)
k0--;
else {
k1++;
k0 = k1 - 1;
}
}
if (flag)
count = 1LL * (count + 1) % mod;
delete [] temp;
}
return count;
}
void generatePowerSet( int arr[], int n)
{
set< int >* power_set
= new set< int >[1 << n];
int mask = 0;
for ( int i = 0; i < (1 << n); i++) {
power_set[i] = getSubset(n, arr, mask);
mask++;
}
cout << countSets(n, power_set) % mod;
delete [] power_set;
}
int main()
{
int arr[] = { 16, 18, 6, 7, 2, 19, 20, 9 };
int N = sizeof (arr) / sizeof (arr[0]);
generatePowerSet(arr, N);
return 0;
}
|
Java
import java.util.*;
class MainClass {
static int mod = 1000000007 ;
static HashSet<Integer> GetSubset( int n, int [] arr, int mask)
{
HashSet<Integer> subset = new HashSet<Integer>();
for ( int i = 0 ; i < n; i++) {
int b = mask & ( 1 << i);
if (b != 0 ) {
subset.add(arr[i]);
}
}
return subset;
}
static int CountSets( int n, HashSet<Integer>[] powerSet) {
int count = 0 ;
for ( int i = 1 ; i < ( 1 << n); i++) {
boolean flag = true ;
int N = powerSet[i].size();
Integer[] temp = powerSet[i].toArray( new Integer[N]);
Arrays.sort(temp, (a, b) -> a - b);
int k1 = 1 ;
int k0 = 0 ;
for (k1 = 1 ; k1 < N;) {
if (temp[k1] % temp[k0] != 0 ) {
flag = false ;
break ;
}
if (k0 > 0 )
k0--;
else {
k1++;
k0 = k1 - 1 ;
}
}
if (flag == true )
count = (count + 1 ) % mod;
}
return count;
}
static void GeneratePowerSet( int [] arr, int n) {
HashSet<Integer>[] powerSet = new HashSet[ 1 << n];
for (var i = 0 ; i < ( 1 << n); i++)
powerSet[i] = new HashSet<Integer>();
var mask = 0 ;
for (var i = 0 ; i < ( 1 << n); i++) {
powerSet[i] = GetSubset(n, arr, mask);
mask++;
}
System.out.println(CountSets(n, powerSet) % mod);
}
public static void main(String[] args)
{
int [] arr = { 16 , 18 , 6 , 7 , 2 , 19 , 20 , 9 };
int N = arr.length;
GeneratePowerSet(arr, N);
}
}
|
Python3
mod = 1000000007
def get_subset(n, arr, mask):
subset = set ()
for i in range (n):
b = mask & ( 1 << i)
if b ! = 0 :
subset.add(arr[i])
return subset
def count_sets(n, power_set):
count = 0
for i in range ( 1 , 1 << n):
flag = True
N = len (power_set[i])
temp = list (power_set[i])
temp.sort(key = lambda x: x)
k1 = 1
k0 = 0
while k1 < N:
if temp[k1] % temp[k0] ! = 0 :
flag = False
break
if k0 > 0 :
k0 - = 1
else :
k1 + = 1
k0 = k1 - 1
if flag:
count = (count + 1 ) % mod
return count
def generate_power_set(arr, n):
power_set = [ set () for _ in range ( 1 << n)]
mask = 0
for i in range ( 1 << n):
power_set[i] = get_subset(n, arr, mask)
mask + = 1
print (count_sets(n, power_set) % mod)
arr = [ 16 , 18 , 6 , 7 , 2 , 19 , 20 , 9 ]
N = len (arr)
generate_power_set(arr, N)
|
C#
using System;
using System.Collections.Generic;
using System.Linq;
class MainClass {
static int mod = 1000000007;
static HashSet< int > GetSubset( int n, int [] arr, int mask)
{
HashSet< int > subset = new HashSet< int >();
for ( int i = 0; i < n; i++) {
int b = mask & (1 << i);
if (b != 0) {
subset.Add(arr[i]);
}
}
return subset;
}
static int CountSets( int n, HashSet< int >[] powerSet) {
int count = 0;
for ( int i = 1; i < (1 << n); i++) {
bool flag = true ;
int N = powerSet[i].Count;
int [] temp = powerSet[i].ToArray();
Array.Sort(temp, (a, b) => a - b);
int k1 = 1;
int k0 = 0;
for (k1 = 1; k1 < N;) {
if (temp[k1] % temp[k0] != 0) {
flag = false ;
break ;
}
if (k0 > 0)
k0--;
else {
k1++;
k0 = k1 - 1;
}
}
if (flag == true )
count = (count + 1) % mod;
}
return count;
}
static void GeneratePowerSet( int [] arr, int n) {
HashSet< int >[] powerSet = new HashSet< int >[1 << n];
for ( var i = 0; i < (1 << n); i++)
powerSet[i] = new HashSet< int >();
var mask = 0;
for ( var i = 0; i < (1 << n); i++) {
powerSet[i] = GetSubset(n, arr, mask);
mask++;
}
Console.WriteLine(CountSets(n, powerSet) % mod);
}
public static void Main( string [] args)
{
int [] arr = { 16, 18, 6, 7, 2, 19, 20, 9 };
int N = arr.Length;
GeneratePowerSet(arr, N);
}
}
|
Javascript
let mod = 1000000007
function getSubset(n, arr, mask)
{
let subset = new Set();
for ( var i = 0; i < n; i++) {
var b = (mask & (1 << i));
if (b != 0) {
subset.add(arr[i]);
}
}
return subset;
}
function countSets( n, power_set)
{
var count = 0;
for ( var i = 1; i < (1 << n); i++) {
var flag = true ;
var N = power_set[i].size;
let temp = Array.from(power_set[i])
temp.sort( function (a, b)
{
return a - b;
})
var k1 = 1;
var k0 = 0;
for (k1 = 1; k1 < N;) {
if (temp[k1] % temp[k0] != 0) {
flag = false ;
break ;
}
if (k0 > 0)
k0--;
else {
k1++;
k0 = k1 - 1;
}
}
if (flag == true )
count = (count + 1) % mod;
}
return count;
}
function generatePowerSet(arr, n)
{
let power_set = new Array(1 << n)
for ( var i = 0; i < (1 << n); i++)
power_set[i] = new Set()
var mask = 0;
for ( var i = 0; i < (1 << n); i++) {
power_set[i] = getSubset(n, arr, mask);
mask++;
}
console.log (countSets(n, power_set) % mod);
}
var arr = [ 16, 18, 6, 7, 2, 19, 20, 9 ];
var N = arr.length;
generatePowerSet(arr, N);
|
Time Complexity: O(N*2N)
Auxiliary Space: O(1)
HashMap-based Approach: To optimize the above approach, the idea is to use a hashmap and an array dp[] to store the array elements in a sorted manner and keeps a count of the subsets as well. For index i, dp[arr[i]] will store the number of all subsets satisfying the given conditions ending at index i. Follow the steps below to solve the problem:
- Initialize cnt as 0 to store the number of required subsets.
- Initialize a hashmap, dp and mark dp[arr[i]] with 1 for every i over the range [0, N – 1].
- Traverse the array dp[] using the variable i and nested traverse from i to begin using iterator j and if i is not equal to j, and element at j is a factor of the element at i, then update dp[i] += dp[j].
- Again, traverse the map and update cnt as cnt += dp[i].
- After the above steps, print the value of cnt as the result.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
#define mod 1000000007
using namespace std;
void countSets( int * arr, int n)
{
map< int , int > dp;
for ( int i = 0; i < n; i++)
dp[arr[i]] = 1;
map< int , int >::iterator i = dp.begin();
for (; i != dp.end(); i++) {
map< int , int >::iterator j = i;
for (; j != dp.begin(); j--) {
if (i == j)
continue ;
if (i->first % j->first == 0) {
i->second
= (i->second % mod
+ j->second % mod)
% mod;
}
}
if (i != j
&& i->first % j->first == 0) {
i->second
= (i->second % mod
+ j->second % mod)
% mod;
}
}
int cnt = 0;
for (i = dp.begin(); i != dp.end(); i++)
cnt = (cnt % mod
+ i->second % mod)
% mod;
cout << cnt % mod;
}
int main()
{
int arr[] = { 16, 18, 6, 7, 2, 19, 20, 9 };
int N = sizeof (arr) / sizeof (arr[0]);
countSets(arr, N);
return 0;
}
|
Java
import java.util.*;
import java.util.TreeMap;
public class Main
{
static void countSets( int [] arr)
{
TreeMap<Integer, Integer> dp = new TreeMap<>();
for ( int i = 0 ; i < arr.length; i++)
dp.put(arr[i], 1 );
for (Map.Entry<Integer, Integer> i :
dp.entrySet()) {
for (Map.Entry<Integer, Integer> j :
dp.headMap(i.getKey()).entrySet()) {
if (i.getKey() == j.getKey())
continue ;
if (i.getKey() % j.getKey() == 0 ) {
i.setValue(
(i.getValue() + j.getValue()));
}
}
}
int cnt = 0 ;
for (Map.Entry<Integer, Integer> i : dp.entrySet())
cnt += i.getValue();
System.out.println(cnt);
}
public static void main(String[] args)
{
int [] arr = { 16 , 18 , 6 , 7 , 2 , 19 , 20 , 9 };
countSets(arr);
}
}
|
Python3
MOD = 1000000007
def countSets(arr, n):
dp = {}
for i in range (n):
dp[arr[i]] = 1
for i in sorted (dp):
for j in reversed ( list (dp.keys())):
if i = = j:
continue
if i % j = = 0 :
dp[i] = (dp[i] % MOD + dp[j] % MOD) % MOD
if i ! = list (dp.keys())[ 0 ] and i % list (dp.keys())[ 0 ] = = 0 :
dp[i] = (dp[i] % MOD + dp[ list (dp.keys())[ 0 ]] % MOD) % MOD
cnt = 0
for i in dp:
cnt = (cnt % MOD + dp[i] % MOD) % MOD
print (cnt % MOD)
arr = [ 16 , 18 , 6 , 7 , 2 , 19 , 20 , 9 ]
N = len (arr
countSets(arr, N)
|
C#
using System;
using System.Collections.Generic;
using System.Linq;
class GFG {
static void CountSets( int [] arr)
{
SortedDictionary< int , int > dp
= new SortedDictionary< int , int >();
for ( int i = 0; i < arr.Length; i++)
dp.Add(arr[i], 1);
for ( int i = 0; i < dp.Count; i++) {
KeyValuePair< int , int > outer = dp.ElementAt(i);
for ( int j = 0; j < i; j++) {
KeyValuePair< int , int > inner
= dp.ElementAt(j);
if (outer.Key == inner.Key)
continue ;
if (outer.Key % inner.Key == 0) {
dp[outer.Key]
= dp[outer.Key] + dp[inner.Key];
}
}
}
int cnt = 0;
foreach (KeyValuePair< int , int > i in dp)
cnt
+= i.Value;
Console.WriteLine(cnt);
}
public static void Main( string [] args)
{
int [] arr = { 16, 18, 6, 7, 2, 19, 20, 9 };
CountSets(arr);
}
}
|
Javascript
let dp = new Map();
function countSets(arr) {
for (let i = 0; i < arr.length; i++) {
dp.set(arr[i], 1);
}
for (let [iKey, iValue] of dp) {
for (let [jKey, jValue] of Array.from(dp.entries()).slice(0, dp.size - dp.get(iKey))) {
if (iKey == jKey) {
continue ;
}
if (iKey % jKey == 0) {
dp.set(iKey, (iValue + jValue));
}
}
}
let cnt = 0;
for (let [key, value] of dp) {
cnt += value;
}
console.log(cnt);
}
let arr = [16, 18, 6, 7, 2, 19, 20, 9];
countSets(arr);
|
Time Complexity: O(N2)
Auxiliary Space: O(N)
Efficient Approach: To optimize the above approach, the idea is to use the similar concept to Sieve of Eratosthenes. Follow the steps below to solve the problem:
- Create an array sieve[] of size greatest element in the array(say maxE), arr[] and initialize with 0s.
- Set sieve[i] = 1 where i is the elements of the array.
- Traverse the array sieve[] over the range [1, maxE]using the variable i and if the value of sieve[i] is positive then add the sieve[i] to all the multiples of i(say j) if the sieve[j] is positive.
- After completing the above steps, print the sum of the elements of the array sieve[] as the result.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
#define mod 1000000007
using namespace std;
void countSets( int * arr, int n)
{
int cnt = 0;
int maxE = -1;
for ( int i = 0; i < n; i++) {
if (maxE < arr[i])
maxE = arr[i];
}
int * sieve = new int [maxE + 1];
for ( int i = 0; i <= maxE; i++)
sieve[i] = 0;
for ( int i = 0; i < n; i++)
sieve[arr[i]] = 1;
for ( int i = 1; i <= maxE; i++) {
if (sieve[i] != 0) {
for ( int j = i * 2; j <= maxE; j += i) {
if (sieve[j] != 0)
sieve[j] = (sieve[j] + sieve[i])
% mod;
}
}
}
for ( int i = 0; i <= maxE; i++)
cnt = (cnt % mod + sieve[i] % mod) % mod;
delete [] sieve;
cout << cnt % mod;
}
int main()
{
int arr[] = { 16, 18, 6, 7, 2, 19, 20, 9 };
int N = sizeof (arr) / sizeof (arr[0]);
countSets(arr, N);
return 0;
}
|
Java
import java.io.*;
import java.util.*;
class GFG {
static int mod = 1000000007 ;
static void countSets( int arr[], int n)
{
int cnt = 0 ;
int maxE = - 1 ;
for ( int i = 0 ; i < n; i++) {
if (maxE < arr[i])
maxE = arr[i];
}
int sieve[] = new int [maxE + 1 ];
for ( int i = 0 ; i < n; i++)
sieve[arr[i]] = 1 ;
for ( int i = 1 ; i <= maxE; i++) {
if (sieve[i] != 0 ) {
for ( int j = i * 2 ; j <= maxE; j += i) {
if (sieve[j] != 0 )
sieve[j]
= (sieve[j] + sieve[i]) % mod;
}
}
}
for ( int i = 0 ; i <= maxE; i++)
cnt = (cnt % mod + sieve[i] % mod) % mod;
System.out.println(cnt % mod);
}
public static void main(String[] args)
{
int arr[] = { 16 , 18 , 6 , 7 , 2 , 19 , 20 , 9 };
int N = arr.length;
countSets(arr, N);
}
}
|
Python3
def countSets(arr, n):
cnt = 0
maxE = - 1
for i in range (n):
if (maxE < arr[i]):
maxE = arr[i]
sieve = [ 0 ] * (maxE + 1 )
for i in range (n):
sieve[arr[i]] = 1
for i in range ( 1 , maxE + 1 ):
if (sieve[i] ! = 0 ):
for j in range (i * 2 , maxE + 1 , i):
if (sieve[j] ! = 0 ):
sieve[j] = (sieve[j] + sieve[i]) % 1000000007
for i in range (maxE + 1 ):
cnt = (cnt % 1000000007 + sieve[i] % 1000000007 ) % 1000000007
print (cnt % 1000000007 )
if __name__ = = '__main__' :
arr = [ 16 , 18 , 6 , 7 , 2 , 19 , 20 , 9 ]
N = len (arr)
countSets(arr, N)
|
C#
using System;
class GFG {
static int mod = 1000000007;
static void countSets( int [] arr, int n)
{
int cnt = 0;
int maxE = -1;
for ( int i = 0; i < n; i++) {
if (maxE < arr[i])
maxE = arr[i];
}
int [] sieve = new int [maxE + 1];
for ( int i = 0; i < n; i++)
sieve[arr[i]] = 1;
for ( int i = 1; i <= maxE; i++) {
if (sieve[i] != 0) {
for ( int j = i * 2; j <= maxE; j += i) {
if (sieve[j] != 0)
sieve[j]
= (sieve[j] + sieve[i]) % mod;
}
}
}
for ( int i = 0; i <= maxE; i++)
cnt = (cnt % mod + sieve[i] % mod) % mod;
Console.WriteLine(cnt % mod);
}
public static void Main( string [] args)
{
int [] arr = { 16, 18, 6, 7, 2, 19, 20, 9 };
int N = arr.Length;
countSets(arr, N);
}
}
|
Javascript
<script>
let mod = 1000000007;
function countSets(arr,n)
{
let cnt = 0;
let maxE = -1;
for (let i = 0; i < n; i++) {
if (maxE < arr[i])
maxE = arr[i];
}
let sieve = new Array(maxE + 1);
for (let i=0;i<maxE + 1;i++)
{
sieve[i]=0;
}
for (let i = 0; i < n; i++)
sieve[arr[i]] = 1;
for (let i = 1; i <= maxE; i++) {
if (sieve[i] != 0) {
for (let j = i * 2; j <= maxE; j += i) {
if (sieve[j] != 0)
sieve[j]
= (sieve[j] + sieve[i]) % mod;
}
}
}
for (let i = 0; i <= maxE; i++)
cnt = (cnt % mod + sieve[i] % mod) % mod;
document.write(cnt % mod+ "<br>" );
}
let arr=[16, 18, 6, 7, 2, 19, 20, 9 ];
let N = arr.length;
countSets(arr, N);
</script>
|
Time Complexity: O(maxE*log(log (maxE)))
Auxiliary Space: O(maxE)
Share your thoughts in the comments
Please Login to comment...