给定一个整数数组,请找到多个子序列,使得该子序列的和可被m整除。假设数组元素之和很小。
例子:
Input : arr[] = {1, 2, 3};
m = 3;
Output : 3
Subsequence of given set are
{1}, {2}, {3}, {1, 2}, {2, 3}, {1, 3} and {1, 2, 3}.
And their sums are 1, 2, 3, 3, 5, 4 and 6.
Input : arr[] = {1, 2, 3, 4};
m = 2;
Output : 7
{2}, {4}, {1, 3}, {2, 4}, {1, 2, 3}, {1, 3, 4}
and {1, 2, 3, 4}
一个简单的解决方案是生成所有可能的子集。对于每个子集,计算其总和,如果总和是m的倍数,则将结果递增1。此方法的时间复杂度为O(2 len ) ,其中len是输入数组的长度。
一个有效的解决方案(小值)基于子集和问题的动态规划解决方案。我们制作一个大小为sum x n的2D数组。
C++
// C++ program which returns the Number of sub sequences
// (or subsets) which are divisible by m.
#include
using namespace std;
// Use Dynamic Programming to find
// sum of subsequences.
int sumSubSequence(vector arr, int len, int m)
{
// Find sum pf array elements
int sum = 0;
for (auto x : arr)
sum += x;
// dp[i][j] would be > 0 if arr[0..i-1] has
// a subsequence with sum equal to j.
vector > dp(len + 1, vector(sum + 1, 0));
// There is always sum equals zero
for (int i = 0; i <= len; i++)
dp[i][0]++;
// Fill up the dp table
for (int i = 1; i <= len; i++) {
dp[i][arr[i - 1]]++;
for (int j = 1; j <= sum; j++) {
if (dp[i - 1][j] > 0) {
dp[i][j]++;
dp[i][j + arr[i - 1]]++;
}
}
}
// Initialize the counter
int count = 0;
for (int j = 1; j <= sum; j++)
// Check if the sum exists
if (dp[len][j] > 0)
// check sum is divisible by m
if (j % m == 0)
count += dp[len][j];
return count;
}
// Driver Code
int main()
{
vector arr{ 1, 2, 3 };
int m = 3;
int len = arr.size();
cout << sumSubSequence(arr, len, m) << endl;
return 0;
}
Java
// Java program which returns the Number of sub sequences
// (or subsets) which are divisible by m.
class GFG
{
// Use Dynamic Programming to find
// sum of subsequences.
static int sumSubSequence(int []arr, int len, int m)
{
// Find sum pf array elements
int sum = 0;
for (int x : arr)
{
sum += x;
}
// dp[i][j] would be > 0 if arr[0..i-1] has
// a subsequence with sum equal to j.
int [][]dp = new int[len + 1][sum + 1];
// There is always sum equals zero
for (int i = 0; i <= len; i++)
dp[i][0]++;
// Fill up the dp table
for (int i = 1; i <= len; i++)
{
dp[i][arr[i - 1]]++;
for (int j = 1; j <= sum; j++)
{
if (dp[i - 1][j] > 0)
{
dp[i][j]++;
dp[i][j + arr[i - 1]]++;
}
}
}
// Initialize the counter
int count = 0;
for (int j = 1; j <= sum; j++)
// Check if the sum exists
if (dp[len][j] > 0)
// check sum is divisible by m
if (j % m == 0)
count += dp[len][j];
return count;
}
// Driver Code
public static void main(String[] args)
{
int []arr = { 1, 2, 3 };
int m = 3;
int len = arr.length;
System.out.print(sumSubSequence(arr, len, m) +"\n");
}
}
// This code is contributed by Rajput-Ji
Python3
# Python3 program which returns
# the Number of sub sequences
# (or subsets) which are divisible by m.
# Use Dynamic Programming to find
# sum of subsequences.
def sumSubSequence(arr, length, m):
# Find sum pf array elements
summ = 0
for i in arr:
summ += i
# dp[i][j] would be > 0 if arr[0..i-1] has
# a subsequence with sum equal to j.
dp = [[0 for i in range(summ + 1)]
for j in range(length + 1)]
# There is always sum equals zero
for i in range(length + 1):
dp[i][0] += 1
# Fill up the dp table
for i in range(1, length + 1):
dp[i][arr[i - 1]] += 1
for j in range(1, summ + 1):
if dp[i - 1][j] > 0:
dp[i][j] += 1
dp[i][j + arr[i - 1]] += 1
# Initialize the counter
count = 0
for i in range(1, summ + 1):
# Check if the sum exists
if dp[length][i] > 0:
# check sum is divisible by m
if i % m == 0:
count += dp[length][i]
return count
# Driver Code
if __name__ == "__main__":
arr = [1, 2, 3]
m = 3
length = len(arr)
print(sumSubSequence(arr, length, m))
# This code is contributed by
# sanjeev2552
C#
// C# program which returns
// the Number of sub sequences
// (or subsets) which are
// divisible by m.
using System;
class GFG{
// Use Dynamic Programming
// to find sum of subsequences.
static int sumSubSequence(int []arr,
int len,
int m)
{
// Find sum pf array elements
int sum = 0;
foreach (int x in arr)
{
sum += x;
}
// dp[i][j] would be > 0 if
// arr[0..i-1] has a
// subsequence with sum equal
// to j.
int [,]dp = new int[len + 1,
sum + 1];
// There is always sum equals
// zero
for (int i = 0; i <= len; i++)
dp[i, 0]++;
// Fill up the dp table
for (int i = 1; i <= len; i++)
{
dp[i, arr[i - 1]]++;
for (int j = 1; j <= sum; j++)
{
if (dp[i - 1, j] > 0)
{
dp[i, j]++;
dp[i, j + arr[i - 1]]++;
}
}
}
// Initialize the counter
int count = 0;
for (int j = 1; j <= sum; j++)
// Check if the sum exists
if (dp[len, j] > 0)
// check sum is divisible
// by m
if (j % m == 0)
count += dp[len, j];
return count;
}
// Driver Code
public static void Main(string[] args)
{
int []arr = {1, 2, 3};
int m = 3;
int len = arr.Length;
Console.Write(
sumSubSequence(arr,
len, m) + "\n");
}
}
// This code is contributed by Chitranayal
输出:
3
上述方法的时间复杂度为O(len * sum) ,其中len是数组的大小,sum是数组中所有整数的总和。