Skip to content
Related Articles

Related Articles

Improve Article

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

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

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 <bits/stdc++.h>
#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[0]);
 
    // 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 <bits/stdc++.h>
#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[0]);
 
    // 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 <bits/stdc++.h>
#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[0]);
 
    // 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




<script>
 
// JavaScript Program to implement
// the above approach
 
let mod = 1000000007;
 
// Function to find number of subsets
  // satisfying the given condition
function countSets(arr,n)
{
    // Stores number of required sets
    let cnt = 0;
  
    // Stores maximum element of arr[]
    // that defines the size of sieve
    let maxE = -1;
  
    // Iterate through the arr[]
    for (let 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
    let sieve = new Array(maxE + 1);
     for(let i=0;i<maxE + 1;i++)
    {
        sieve[i]=0;
    }
     
    // Mark all elements corresponding in
    // the array, by one as there will
    // always exists a singleton set
    for (let i = 0; i < n; i++)
      sieve[arr[i]] = 1;
  
    // Iterate from range [1, N]
    for (let i = 1; i <= maxE; i++) {
  
      // If element is present in array
      if (sieve[i] != 0) {
  
        // Traverse through all its
        // multiples <= n
        for (let 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 (let i = 0; i <= maxE; i++)
  
      // Update the value of cnt
      cnt = (cnt % mod + sieve[i] % mod) % mod;
  
    // Print the result
    document.write(cnt % mod+"<br>");
}
 
// Driver Code
let arr=[16, 18, 6, 7, 2, 19, 20, 9 ];
let N = arr.length;
 
// Function Call
countSets(arr, N);
 
 
// This code is contributed by avanitrachhadiya2155
 
</script>

 
 

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
Recommended Articles
Page :