给定大小为N的数组arr [] ,任务是查找数组中存在的非空子集的数量,以使子集中的每个元素(最后一个元素除外)都是该子集中存在的下一个相邻元素的因子。子集中的元素可以重新排列,因此,如果子集中的任何重新排列满足条件,则该子集中将被计入。但是,该子集应仅被计数一次。
例子:
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
简单方法:最简单的想法是,以产生阵列的所有可能的子集,并打印这些亚群,其相邻的元件(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,DP和DP标记[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)