给定一个由N个整数组成的数组arr []和一个整数M ,任务是找到非空子序列的数量,以使子序列的和可被M整除。
例子:
Input: arr[] = {1, 2, 3}, M = 1
Output: 7
Number of non-empty subsets of this array are 7.
Since m = 1, m will divide all the possible subsets.
Input: arr[] = {1, 2, 3}, M = 2
Output: 3
方法:本文讨论了一种基于动态编程的方法,该方法具有O(N * SUM)时间复杂度,其中N是数组的长度, SUM是所有数组元素的总和。
在本文中,将讨论对先前方法的改进。代替总和作为DP的状态之一,(总和%m)将用作DP的状态之一,因为足够了。因此,时间复杂度可以归结为O(m * N)。
递归关系:
dp[i][curr] = dp[i + 1][(curr + arr[i]) % m] + dp[i + 1][curr]
现在让我们定义状态, dp [i] [curr]仅仅表示子数组arr [i…N-1]的子集数,从而(其元素的总和+ curr)%m = 0 。
下面是上述方法的实现:
C++
// C++ implementation of the approach
#include
using namespace std;
#define maxN 20
#define maxM 10
// To store the states of DP
int dp[maxN][maxM];
bool v[maxN][maxM];
// Function to find the required count
int findCnt(int* arr, int i, int curr, int n, int m)
{
// Base case
if (i == n) {
if (curr == 0)
return 1;
else
return 0;
}
// If the state has been solved before
// return the value of the state
if (v[i][curr])
return dp[i][curr];
// Setting the state as solved
v[i][curr] = 1;
// Recurrence relation
return dp[i][curr] = findCnt(arr, i + 1,
curr, n, m)
+ findCnt(arr, i + 1,
(curr + arr[i]) % m,
n, m);
}
// Driver code
int main()
{
int arr[] = { 3, 3, 3, 3 };
int n = sizeof(arr) / sizeof(int);
int m = 6;
cout << findCnt(arr, 0, 0, n, m) - 1;
return 0;
}
Java
// Java implementation of the approach
class GFG
{
static int maxN = 20;
static int maxM = 10;
// To store the states of DP
static int [][]dp = new int[maxN][maxM];
static boolean [][]v = new boolean[maxN][maxM];
// Function to find the required count
static int findCnt(int[] arr, int i,
int curr, int n, int m)
{
// Base case
if (i == n)
{
if (curr == 0)
return 1;
else
return 0;
}
// If the state has been solved before
// return the value of the state
if (v[i][curr])
return dp[i][curr];
// Setting the state as solved
v[i][curr] = true;
// Recurrence relation
return dp[i][curr] = findCnt(arr, i + 1,
curr, n, m) +
findCnt(arr, i + 1,
(curr + arr[i]) % m,
n, m);
}
// Driver code
public static void main(String[] args)
{
int arr[] = { 3, 3, 3, 3 };
int n = arr.length;
int m = 6;
System.out.println(findCnt(arr, 0, 0, n, m) - 1);
}
}
// This code is contributed by 29AjayKumar
Python3
# Python3 implementation of the approach
maxN = 20
maxM = 10
# To store the states of DP
dp = [[0 for i in range(maxN)]
for i in range(maxM)]
v = [[0 for i in range(maxN)]
for i in range(maxM)]
# Function to find the required count
def findCnt(arr, i, curr, n, m):
# Base case
if (i == n):
if (curr == 0):
return 1
else:
return 0
# If the state has been solved before
# return the value of the state
if (v[i][curr]):
return dp[i][curr]
# Setting the state as solved
v[i][curr] = 1
# Recurrence relation
dp[i][curr] = findCnt(arr, i + 1,
curr, n, m) + \
findCnt(arr, i + 1,
(curr + arr[i]) % m, n, m)
return dp[i][curr]
# Driver code
arr = [3, 3, 3, 3]
n = len(arr)
m = 6
print(findCnt(arr, 0, 0, n, m) - 1)
# This code is contributed by Mohit Kumar
C#
// C# implementation of the approach
using System;
class GFG
{
static int maxN = 20;
static int maxM = 10;
// To store the states of DP
static int [,]dp = new int[maxN, maxM];
static bool [,]v = new bool[maxN, maxM];
// Function to find the required count
static int findCnt(int[] arr, int i,
int curr, int n, int m)
{
// Base case
if (i == n)
{
if (curr == 0)
return 1;
else
return 0;
}
// If the state has been solved before
// return the value of the state
if (v[i, curr])
return dp[i, curr];
// Setting the state as solved
v[i, curr] = true;
// Recurrence relation
return dp[i, curr] = findCnt(arr, i + 1,
curr, n, m) +
findCnt(arr, i + 1,
(curr + arr[i]) % m, n, m);
}
// Driver code
public static void Main()
{
int []arr = { 3, 3, 3, 3 };
int n = arr.Length;
int m = 6;
Console.WriteLine(findCnt(arr, 0, 0, n, m) - 1);
}
}
// This code is contributed by kanugargng
Javascript
输出:
7