给定大小为N且整数K的数组arr [] ,任务是计算给定数组中元素乘以K的乘积的子集数
例子:
Input: arr[] = {1, 2, 3, 4, 5}, K = 60
Output: 4
Explanation: Subsets whose product of elements is divisible by K(= 60) are { {1, 2, 3, 4, 5}, {2, 3, 4, 5}, {3, 4, 5}, {1, 3, 4, 5} }
Input: arr[] = {1, 2, 3, 4, 5, 6}, K = 60
Output: 16
天真的方法:解决此问题的最简单方法是生成所有可能的子集,并针对每个子集检查其元素乘积是否可被K整除。如果发现是真的,则增加计数。最后,打印计数。
时间复杂度: O(N * 2 N )
辅助空间: O(N)
高效方法:为了优化上述方法,其思想是使用动态编程。以下是递归关系和基本情况:
Recurrence Relation:
cntSubDivK(N, rem) = cntSubDivK(N – 1, (rem * arr[N – 1]) % K) + cntSubDivK(N – 1, rem).
cntSubDivK(N, rem) store the count of subset having product divisible by K.
rem: Store the remainder when K divides the product of all elements of the subset.
Base Case:
if N == 0 and rem == 0 then return 1.
If N == 0 and rem != 0 then return 0.
请按照以下步骤解决问题:
- 初始化一个二维数组,例如dp [N] [rem],以计算和存储上述递归关系的所有子问题的值。
- 最后,返回dp [N] [rem]的值。
下面是上述方法的实现:
C++
// C++ program to implement
// the above approach
#include
using namespace std;
// Function to count the subsets whose
// product of elements is divisible by K
int cntSubDivK(int arr[], int N, int K,
int rem, vector >& dp)
{
// If count of elements
// in the array is 0
if (N == 0) {
// If rem is 0, then return 1
// Otherwise, return 0
return rem == 0;
}
// If already computed
// subproblem occurred
if (dp[N][rem] != -1) {
return dp[N][rem];
}
// Stores count of subsets having product
// divisible by K when arr[N - 1]
// present in the subset
int X = cntSubDivK(arr, N - 1, K,
(rem * arr[N - 1]) % K, dp);
// Stores count of subsets having product
// divisible by K when arr[N - 1] not
// present in the subset
int Y = cntSubDivK(arr, N - 1, K,
rem, dp);
// Return total subset
return X + Y;
}
// Utility Function to count the subsets whose
// product of elements is divisible by K
int UtilCntSubDivK(int arr[], int N, int K)
{
// Initialize a 2D array to store values
// of overlapping subproblems
vector > dp(N + 1,
vector(K + 1, -1));
return cntSubDivK(arr, N, K, 1, dp);
}
// Driver Code
int main()
{
int arr[] = { 1, 2, 3, 4, 5, 6 };
int K = 60;
int N = sizeof(arr) / sizeof(arr[0]);
cout << UtilCntSubDivK(arr, N, K);
}
Java
// Java program to implement
// the above approach
import java.util.*;
class GFG{
// Function to count the subsets whose
// product of elements is divisible by K
static int cntSubDivK(int arr[], int N, int K,
int rem, int[][]dp)
{
// If count of elements
// in the array is 0
if (N == 0)
{
// If rem is 0, then return 1
// Otherwise, return 0
return rem == 0 ? 1 : 0;
}
// If already computed
// subproblem occurred
if (dp[N][rem] != -1)
{
return dp[N][rem];
}
// Stores count of subsets having product
// divisible by K when arr[N - 1]
// present in the subset
int X = cntSubDivK(arr, N - 1, K,
(rem * arr[N - 1]) % K, dp);
// Stores count of subsets having product
// divisible by K when arr[N - 1] not
// present in the subset
int Y = cntSubDivK(arr, N - 1, K,
rem, dp);
// Return total subset
return X + Y;
}
// Utility Function to count the subsets whose
// product of elements is divisible by K
static int UtilCntSubDivK(int arr[], int N, int K)
{
// Initialize a 2D array to store values
// of overlapping subproblems
int [][]dp = new int[N + 1][K + 1];
for(int i = 0; i < N + 1; i++)
{
for(int j = 0; j < K + 1; j++)
dp[i][j] = -1;
}
return cntSubDivK(arr, N, K, 1, dp);
}
// Driver Code
public static void main(String args[])
{
int arr[] = { 1, 2, 3, 4, 5, 6 };
int K = 60;
int N = arr.length;
System.out.println(UtilCntSubDivK(arr, N, K));
}
}
// This code is contributed by SURENDRA_GANGWAR
Python3
# Python3 program to
# implement the above
# approach
# Function to count the
# subsets whose product
# of elements is divisible
# by K
def cntSubDivK(arr, N, K,
rem, dp):
# If count of elements
# in the array is 0
if (N == 0):
# If rem is 0, then
# return 1 Otherwise,
# return 0
return rem == 0
# If already computed
# subproblem occurred
if (dp[N][rem] != -1):
return dp[N][rem]
# Stores count of subsets
# having product divisible
# by K when arr[N - 1]
# present in the subset
X = cntSubDivK(arr, N - 1, K,
(rem * arr[N - 1]) % K, dp)
# Stores count of subsets having
# product divisible by K when
# arr[N - 1] not present in
# the subset
Y = cntSubDivK(arr, N - 1,
K, rem, dp)
# Return total subset
return X + Y
# Utility Function to count
# the subsets whose product of
# elements is divisible by K
def UtilCntSubDivK(arr, N, K):
# Initialize a 2D array to
# store values of overlapping
# subproblems
dp = [[-1 for x in range(K + 1)]
for y in range(N + 1)]
return cntSubDivK(arr, N,
K, 1, dp)
# Driver Code
if __name__ == "__main__":
arr = [1, 2, 3,
4, 5, 6]
K = 60
N = len(arr)
print(UtilCntSubDivK(arr, N, K))
# This code is contributed by Chitranayal
C#
// C# program to implement
// the above approach
using System;
class GFG{
// Function to count the subsets whose
// product of elements is divisible by K
static int cntSubDivK(int[] arr, int N, int K,
int rem, int[,] dp)
{
// If count of elements
// in the array is 0
if (N == 0)
{
// If rem is 0, then return 1
// Otherwise, return 0
return rem == 0 ? 1 : 0;
}
// If already computed
// subproblem occurred
if (dp[N, rem] != -1)
{
return dp[N, rem];
}
// Stores count of subsets having product
// divisible by K when arr[N - 1]
// present in the subset
int X = cntSubDivK(arr, N - 1, K,
(rem * arr[N - 1]) % K, dp);
// Stores count of subsets having product
// divisible by K when arr[N - 1] not
// present in the subset
int Y = cntSubDivK(arr, N - 1, K,
rem, dp);
// Return total subset
return X + Y;
}
// Utility Function to count the subsets whose
// product of elements is divisible by K
static int UtilCntSubDivK(int[] arr, int N, int K)
{
// Initialize a 2D array to store values
// of overlapping subproblems
int[,] dp = new int[N + 1, K + 1];
for(int i = 0; i < N + 1; i++)
{
for(int j = 0; j < K + 1; j++)
dp[i, j] = -1;
}
return cntSubDivK(arr, N, K, 1, dp);
}
// Driver code
static void Main()
{
int[] arr = { 1, 2, 3, 4, 5, 6 };
int K = 60;
int N = arr.Length;
Console.WriteLine(UtilCntSubDivK(arr, N, K));
}
}
// This code is contributed by divyeshrabadiya07
16
时间复杂度: O(N * K)
空间复杂度: O(N * K)