Related Articles

# Count subsets consisting of each element as a factor of the next element in that subset

• Difficulty Level : Medium
• Last Updated : 24 Sep, 2021

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++

 `// C++ program for the above approach` `#include ``#define mod 1000000007``using` `namespace` `std;` `// Function to calculate each subset``// for the array using bit masking``set<``int``> getSubset(``int` `n, ``int``* arr,``                   ``int` `mask)``{``    ``// Stores the unique elements``    ``// of the array arr[]``    ``set<``int``> subset;` `    ``// Traverse the array``    ``for` `(``int` `i = 0; i < n; i++) {` `        ``// Get the ith bit of the mask``        ``int` `b = (mask & (1 << i));` `        ``// ith bit of mask is set then``        ``// include the corresponding``        ``// element in subset``        ``if` `(b != 0) {``            ``subset.insert(arr[i]);``        ``}``    ``}``    ``return` `subset;``}` `// Function to count the subsets``// that satisfy the given condition``int` `countSets(``int` `n, set<``int``>* power_set)``{``    ``// Store the count of subsets``    ``int` `count = 0;` `    ``// Iterate through all the sets``    ``// in the power set``    ``for` `(``int` `i = 1; i < (1 << n); i++) {` `        ``// Initially, set flag as true``        ``bool` `flag = ``true``;` `        ``int` `N = power_set[i].size();` `        ``// Convert the current subset``        ``// into an array``        ``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;``        ``}` `        ``// Check for any index, i,``        ``// a[i] is a factor of a[i+1]``        ``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 is stil set, then``        ``// update the count``        ``if` `(flag)``            ``count = 1LL * (count + 1) % mod;` `        ``delete``[] temp;``    ``}` `    ``// Return the final count``    ``return` `count;``}` `// Function to generate power set of``// the given array arr[]``void` `generatePowerSet(``int` `arr[], ``int` `n)``{` `    ``// Declare power set of size 2^n``    ``set<``int``>* power_set``        ``= ``new` `set<``int``>[1 << n];` `    ``// Represent each subset using``    ``// some mask``    ``int` `mask = 0;``    ``for` `(``int` `i = 0; i < (1 << n); i++) {``        ``power_set[i] = getSubset(n, arr, mask);``        ``mask++;``    ``}` `    ``// Find the required number of``    ``// subsets``    ``cout << countSets(n, power_set) % mod;` `    ``delete``[] power_set;``}` `// Driver Code``int` `main()``{``    ``int` `arr[] = { 16, 18, 6, 7, 2, 19, 20, 9 };``    ``int` `N = ``sizeof``(arr) / ``sizeof``(arr);` `    ``// Function Call``    ``generatePowerSet(arr, N);` `    ``return` `0;``}`
Output:
`15`

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++

 `// C++ program for the above approach``#include ``#define mod 1000000007``using` `namespace` `std;` `// Function that counts subsets whose``// every element is divisible by the``// previous adjacent element``void` `countSets(``int``* arr, ``int` `n)``{``    ``// Declare a map``    ``map<``int``, ``int``> dp;` `    ``// Initialise dp[arr[i]] with 1``    ``for` `(``int` `i = 0; i < n; i++)``        ``dp[arr[i]] = 1;` `    ``// Traverse the map till end``    ``map<``int``, ``int``>::iterator i = dp.begin();` `    ``for` `(; i != dp.end(); i++) {` `        ``// Traverse the map from i to``        ``// begin using iterator j``        ``map<``int``, ``int``>::iterator j = i;` `        ``for` `(; j != dp.begin(); j--) {` `            ``if` `(i == j)``                ``continue``;` `            ``// Check if condition is true``            ``if` `(i->first % j->first == 0) {` `                ``// If factor found, append``                ``// i at to all subsets``                ``i->second``                    ``= (i->second % mod``                       ``+ j->second % mod)``                      ``% mod;``            ``}``        ``}` `        ``// Check for the first element``        ``// of the map``        ``if` `(i != j``            ``&& i->first % j->first == 0) {``            ``i->second``                ``= (i->second % mod``                   ``+ j->second % mod)``                  ``% mod;``        ``}``    ``}` `    ``// Store count of required subsets``    ``int` `cnt = 0;` `    ``// Traverse the map``    ``for` `(i = dp.begin(); i != dp.end(); i++)` `        ``// Update the cnt variable``        ``cnt = (cnt % mod``               ``+ i->second % mod)``              ``% mod;` `    ``// Print the result``    ``cout << cnt % mod;``}` `// Driver Code``int` `main()``{``    ``int` `arr[] = { 16, 18, 6, 7, 2, 19, 20, 9 };``    ``int` `N = ``sizeof``(arr) / ``sizeof``(arr);` `    ``// Function Call``    ``countSets(arr, N);` `    ``return` `0;``}`

Output:
`15`

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++

 `// C++ program for the above approach``#include ``#define mod 1000000007``using` `namespace` `std;` `// Function to find number of subsets``// satisfying the given condition``void` `countSets(``int``* arr, ``int` `n)``{``    ``// Stores number of required sets``    ``int` `cnt = 0;` `    ``// Stores maximum element of arr[]``    ``// that defines the size of sieve``    ``int` `maxE = -1;` `    ``// Iterate through the arr[]``    ``for` `(``int` `i = 0; i < n; i++) {` `        ``// If current element > maxE,``        ``// then update maxE``        ``if` `(maxE < arr[i])``            ``maxE = arr[i];``    ``}` `    ``// Declare an array sieve of size N + 1``    ``int``* sieve = ``new` `int``[maxE + 1];` `    ``// Initialize with all 0s``    ``for` `(``int` `i = 0; i <= maxE; i++)``        ``sieve[i] = 0;` `    ``// Mark all elements corresponding in``    ``// the array, by one as there will``    ``// always exists a singleton set``    ``for` `(``int` `i = 0; i < n; i++)``        ``sieve[arr[i]] = 1;` `    ``// Iterate from range [1, N]``    ``for` `(``int` `i = 1; i <= maxE; i++) {` `        ``// If element is present in array``        ``if` `(sieve[i] != 0) {` `            ``// Traverse through all its``            ``// multiples <= n``            ``for` `(``int` `j = i * 2; j <= maxE; j += i) {` `                ``// Update them if they``                ``// are present in array``                ``if` `(sieve[j] != 0)``                    ``sieve[j] = (sieve[j] + sieve[i])``                               ``% mod;``            ``}``        ``}``    ``}` `    ``// Iterate from the range [1, N]``    ``for` `(``int` `i = 0; i <= maxE; i++)` `        ``// Update the value of cnt``        ``cnt = (cnt % mod + sieve[i] % mod) % mod;` `    ``delete``[] sieve;` `    ``// Print the result``    ``cout << cnt % mod;``}` `// Driver Code``int` `main()``{``    ``int` `arr[] = { 16, 18, 6, 7, 2, 19, 20, 9 };``    ``int` `N = ``sizeof``(arr) / ``sizeof``(arr);` `    ``// Function Call``    ``countSets(arr, N);` `    ``return` `0;``}`

## Java

 `// Java Program to implement``// the above approach``import` `java.io.*;``import` `java.util.*;` `class` `GFG {` `  ``static` `int` `mod = ``1000000007``;` `  ``// Function to find number of subsets``  ``// satisfying the given condition``  ``static` `void` `countSets(``int` `arr[], ``int` `n)``  ``{``    ``// Stores number of required sets``    ``int` `cnt = ``0``;` `    ``// Stores maximum element of arr[]``    ``// that defines the size of sieve``    ``int` `maxE = -``1``;` `    ``// Iterate through the arr[]``    ``for` `(``int` `i = ``0``; i < n; i++) {` `      ``// If current element > maxE,``      ``// then update maxE``      ``if` `(maxE < arr[i])``        ``maxE = arr[i];``    ``}` `    ``// Declare an array sieve of size N + 1``    ``int` `sieve[] = ``new` `int``[maxE + ``1``];` `    ``// Mark all elements corresponding in``    ``// the array, by one as there will``    ``// always exists a singleton set``    ``for` `(``int` `i = ``0``; i < n; i++)``      ``sieve[arr[i]] = ``1``;` `    ``// Iterate from range [1, N]``    ``for` `(``int` `i = ``1``; i <= maxE; i++) {` `      ``// If element is present in array``      ``if` `(sieve[i] != ``0``) {` `        ``// Traverse through all its``        ``// multiples <= n``        ``for` `(``int` `j = i * ``2``; j <= maxE; j += i) {` `          ``// Update them if they``          ``// are present in array``          ``if` `(sieve[j] != ``0``)``            ``sieve[j]``            ``= (sieve[j] + sieve[i]) % mod;``        ``}``      ``}``    ``}` `    ``// Iterate from the range [1, N]``    ``for` `(``int` `i = ``0``; i <= maxE; i++)` `      ``// Update the value of cnt``      ``cnt = (cnt % mod + sieve[i] % mod) % mod;` `    ``// Print the result``    ``System.out.println(cnt % mod);``  ``}` `  ``// Driver Code``  ``public` `static` `void` `main(String[] args)``  ``{` `    ``int` `arr[] = { ``16``, ``18``, ``6``, ``7``, ``2``, ``19``, ``20``, ``9` `};``    ``int` `N = arr.length;` `    ``// Function Call``    ``countSets(arr, N);``  ``}``}` `// This code is contributed by Kingash.`

## Python3

 `#mod 1000000007` `# Function to find number of subsets``# satisfying the given condition``def` `countSets(arr, n):``  ` `    ``# Stores number of required sets``    ``cnt ``=` `0` `    ``# Stores maximum element of arr[]``    ``# that defines the size of sieve``    ``maxE ``=` `-``1` `    ``# Iterate through the arr[]``    ``for` `i ``in` `range``(n):` `        ``# If current element > maxE,``        ``# then update maxE``        ``if` `(maxE < arr[i]):``            ``maxE ``=` `arr[i]` `    ``# Declare an array sieve of size N + 1``    ``sieve ``=` `[``0``]``*``(maxE ``+` `1``)` `    ``# Mark all elements corresponding in``    ``# the array, by one as there will``    ``# always exists a singleton set``    ``for` `i ``in` `range``(n):``        ``sieve[arr[i]] ``=` `1` `    ``# Iterate from range [1, N]``    ``for` `i ``in` `range``(``1``, maxE ``+` `1``):` `        ``# If element is present in array``        ``if` `(sieve[i] !``=` `0``):` `            ``# Traverse through all its``            ``# multiples <= n``            ``for` `j ``in` `range``(i ``*` `2``, maxE ``+` `1``, i):` `                ``# Update them if they``                ``# are present in array``                ``if` `(sieve[j] !``=` `0``):``                    ``sieve[j] ``=` `(sieve[j] ``+` `sieve[i])``%` `1000000007` `    ``# Iterate from the range [1, N]``    ``for` `i ``in` `range``(maxE ``+` `1``):``      ` `        ``# Update the value of cnt``        ``cnt ``=` `(cnt ``%` `1000000007` `+` `sieve[i] ``%` `1000000007``) ``%` `1000000007` `    ``#delete[] sieve` `    ``# Prthe result``    ``print` `(cnt ``%` `1000000007``)` `# Driver Code``if` `__name__ ``=``=` `'__main__'``:``    ``arr ``=``[``16``, ``18``, ``6``, ``7``, ``2``, ``19``, ``20``, ``9``]``    ``N ``=` `len``(arr)` `    ``# Function Call``    ``countSets(arr, N)` `# This code is contributed by mohit kumar 29.`

## C#

 `// C# Program to implement``// the above approach``using` `System;` `class` `GFG {` `  ``static` `int` `mod = 1000000007;` `  ``// Function to find number of subsets``  ``// satisfying the given condition``  ``static` `void` `countSets(``int``[] arr, ``int` `n)``  ``{``    ``// Stores number of required sets``    ``int` `cnt = 0;` `    ``// Stores maximum element of arr[]``    ``// that defines the size of sieve``    ``int` `maxE = -1;` `    ``// Iterate through the arr[]``    ``for` `(``int` `i = 0; i < n; i++) {` `      ``// If current element > maxE,``      ``// then update maxE``      ``if` `(maxE < arr[i])``        ``maxE = arr[i];``    ``}` `    ``// Declare an array sieve of size N + 1``    ``int``[] sieve = ``new` `int``[maxE + 1];` `    ``// Mark all elements corresponding in``    ``// the array, by one as there will``    ``// always exists a singleton set``    ``for` `(``int` `i = 0; i < n; i++)``      ``sieve[arr[i]] = 1;` `    ``// Iterate from range [1, N]``    ``for` `(``int` `i = 1; i <= maxE; i++) {` `      ``// If element is present in array``      ``if` `(sieve[i] != 0) {` `        ``// Traverse through all its``        ``// multiples <= n``        ``for` `(``int` `j = i * 2; j <= maxE; j += i) {` `          ``// Update them if they``          ``// are present in array``          ``if` `(sieve[j] != 0)``            ``sieve[j]``            ``= (sieve[j] + sieve[i]) % mod;``        ``}``      ``}``    ``}` `    ``// Iterate from the range [1, N]``    ``for` `(``int` `i = 0; i <= maxE; i++)` `      ``// Update the value of cnt``      ``cnt = (cnt % mod + sieve[i] % mod) % mod;` `    ``// Print the result``    ``Console.WriteLine(cnt % mod);``  ``}` `  ``// Driver Code``  ``public` `static` `void` `Main(``string``[] args)``  ``{` `    ``int``[] arr = { 16, 18, 6, 7, 2, 19, 20, 9 };``    ``int` `N = arr.Length;` `    ``// Function Call``    ``countSets(arr, N);``  ``}``}` `// This code is contributed by ukasp.`

## Javascript

 ``

Output:
`15`

Time Complexity: O(maxE*log(log (maxE)))
Auxiliary Space: O(maxE)

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with experts, please refer DSA Live Classes for Working Professionals and Competitive Programming Live for Students.

My Personal Notes arrow_drop_up