📌  相关文章
📜  计算由每个元素组成的子集,作为该子集中下一个元素的因子

📅  最后修改于: 2021-05-18 00:52:43             🧑  作者: Mango

给定大小为N的数组arr [] ,任务是查找数组中存在的非空子集的数量,以使子集中的每个元素(最后一个元素除外)都是该子集中存在的下一个相邻元素的因子。子集中的元素可以重新排列,因此,如果子集的任何重新排列满足条件,则该子集中将被计入。但是,该子集应仅被计数一次。

例子:

简单方法:最简单的想法是,以产生阵列的所有可能的子集,并打印这些亚群,其相邻的元件(ARR [I],ARR第[i + 1]),ARR [I]的计数ARR的因子[I +1]

下面是上述方法的实现:

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 getSubset(int n, int* arr,
                   int mask)
{
    // Stores the unique elements
    // of the array arr[]
    set 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* 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* power_set
        = new set[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;
}


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 dp;
 
    // Initialse dp[arr[i]] with 1
    for (int i = 0; i < n; i++)
        dp[arr[i]] = 1;
 
    // Traverse the map till end
    map::iterator i = dp.begin();
 
    for (; i != dp.end(); i++) {
 
        // Traverse the map from i to
        // begin using iterator j
        map::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;
}


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[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.


输出:
15

时间复杂度: O(N * 2 N )
辅助空间: O(1)

基于HashMap的方法:为了优化上述方法,其思想是使用哈希图和数组dp []以排序的方式存储数组元素,并同时保留子集的数量。对于索引i,dp [arr [i]]将存储满足给定条件的所有子集的数目,这些子集以索引i结尾。请按照以下步骤解决问题:

  • cnt初始化为0,以存储所需子集的数量。
  • 初始化一个HashMap,DPDP标记[ARR [I]]1对每个i在范围[0,N – 1]。
  • 使用变量i遍历数组dp []并从i嵌套遍历以开始使用迭代器j ,如果i不等于j ,并且j处的元素是i处元素的因数,则更新dp [i] + = dp [j]
  • 同样,遍历地图并将cnt更新为cnt + = dp [i]
  • 完成上述步骤后,打印cnt的值作为结果。

下面是上述方法的实现:

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 dp;
 
    // Initialse dp[arr[i]] with 1
    for (int i = 0; i < n; i++)
        dp[arr[i]] = 1;
 
    // Traverse the map till end
    map::iterator i = dp.begin();
 
    for (; i != dp.end(); i++) {
 
        // Traverse the map from i to
        // begin using iterator j
        map::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;
}

输出:
15

时间复杂度: O(N 2 )
辅助空间: O(N)

高效方法:为了优化上述方法,其想法是使用与Eratosthenes筛网相似的概念。请按照以下步骤解决问题:

  • 在数组中创建最大尺寸的数组sieve [] (例如maxE ), arr []并用0s初始化。
  • 设置sieve [i] = 1 ,其中i是数组的元素。
  • 使用变量i在[1,maxE]范围内遍历数组sieve [] ,如果sieve [i]的值为正,则将sieve [i]添加到i的所有倍数(例如j),如果sieve [ j]是肯定的。
  • 完成上述步骤后,将数组sieve []的元素总和打印为结果。

下面是上述方法的实现:

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[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.

输出:
15

时间复杂度: O(maxE * log(log(maxE)))
辅助空间: O(maxE)