给定一个数组arr[]和一个整数M ,任务是找到最长子序列的长度,其总和可以被M整除。如果没有这样的子序列,则打印0 。
例子:
Input: arr[] = {3, 2, 2, 1}, M = 3
Output: 3
Longest sub-sequence whose sum is
divisible by 3 is {3, 2, 1}
Input: arr[] = {2, 2}, M = 3
Output: 0
方法:解决这个问题的一个简单方法是生成所有可能的子序列,然后找到其中最大的可整除其总和可被M整除的。然而,对于较小的M值,可以使用基于动态规划的方法。
我们先来看递归关系。
dp[i][curr_mod] = max(dp[i + 1][curr_mod], dp[i + 1][(curr_mod + arr[i]) % m] + 1)
现在让我们了解DP的状态。这里, dp[i][curr_mod]存储子数组arr[i…N-1]的最长子序列,使得这个子序列和curr_mod 的和可以被M整除。在每一步,可以选择索引i更新curr_mod或者可以忽略它。
另请注意,仅需要存储SUM % m而不是整个总和,因为此信息足以完成 DP 的状态。
下面是上述方法的实现:
C++
// C++ implementation of the approach
#include
using namespace std;
#define maxN 20
#define maxM 64
// To store the states of DP
int dp[maxN][maxM];
bool v[maxN][maxM];
// Function to return the length
// of the longest subsequence
// whose sum is divisible by m
int findLen(int* arr, int i, int curr,
int n, int m)
{
// Base case
if (i == n) {
if (!curr)
return 0;
else
return -1;
}
// 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
int l = findLen(arr, i + 1, curr, n, m);
int r = findLen(arr, i + 1,
(curr + arr[i]) % m, n, m);
dp[i][curr] = l;
if (r != -1)
dp[i][curr] = max(dp[i][curr], r + 1);
return dp[i][curr];
}
// Driver code
int main()
{
int arr[] = { 3, 2, 2, 1 };
int n = sizeof(arr) / sizeof(int);
int m = 3;
cout << findLen(arr, 0, 0, n, m);
return 0;
}
Java
// Java implementation of the approach
class GFG
{
static int maxN = 20;
static int maxM = 64;
// To store the states of DP
static int [][]dp = new int[maxN][maxM];
static boolean [][]v = new boolean[maxN][maxM];
// Function to return the length
// of the longest subsequence
// whose sum is divisible by m
static int findLen(int[] arr, int i,
int curr, int n, int m)
{
// Base case
if (i == n)
{
if (curr == 0)
return 0;
else
return -1;
}
// 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
int l = findLen(arr, i + 1, curr, n, m);
int r = findLen(arr, i + 1,
(curr + arr[i]) % m, n, m);
dp[i][curr] = l;
if (r != -1)
dp[i][curr] = Math.max(dp[i][curr], r + 1);
return dp[i][curr];
}
// Driver code
public static void main(String []args)
{
int arr[] = { 3, 2, 2, 1 };
int n = arr.length;
int m = 3;
System.out.println(findLen(arr, 0, 0, n, m));
}
}
// This code is contributed by 29AjayKumar
Python3
# Python3 implementation of the approach
import numpy as np
maxN = 20
maxM = 64
# To store the states of DP
dp = np.zeros((maxN, maxM));
v = np.zeros((maxN, maxM));
# Function to return the length
# of the longest subsequence
# whose sum is divisible by m
def findLen(arr, i, curr, n, m) :
# Base case
if (i == n) :
if (not curr) :
return 0;
else :
return -1;
# 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
l = findLen(arr, i + 1, curr, n, m);
r = findLen(arr, i + 1,
(curr + arr[i]) % m, n, m);
dp[i][curr] = l;
if (r != -1) :
dp[i][curr] = max(dp[i][curr], r + 1);
return dp[i][curr];
# Driver code
if __name__ == "__main__" :
arr = [ 3, 2, 2, 1 ];
n = len(arr);
m = 3;
print(findLen(arr, 0, 0, n, m));
# This code is contributed by AnkitRai
C#
// C# implementation of the approach
using System;
class GFG
{
static int maxN = 20;
static int maxM = 64;
// To store the states of DP
static int [,]dp = new int[maxN, maxM];
static Boolean [,]v = new Boolean[maxN, maxM];
// Function to return the length
// of the longest subsequence
// whose sum is divisible by m
static int findLen(int[] arr, int i,
int curr, int n, int m)
{
// Base case
if (i == n)
{
if (curr == 0)
return 0;
else
return -1;
}
// 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
int l = findLen(arr, i + 1, curr, n, m);
int r = findLen(arr, i + 1,
(curr + arr[i]) % m, n, m);
dp[i, curr] = l;
if (r != -1)
dp[i, curr] = Math.Max(dp[i, curr], r + 1);
return dp[i, curr];
}
// Driver code
public static void Main(String []args)
{
int []arr = { 3, 2, 2, 1 };
int n = arr.Length;
int m = 3;
Console.WriteLine(findLen(arr, 0, 0, n, m));
}
}
// This code is contributed by 29AjayKumar
Javascript
输出:
3
时间复杂度: O(N * M)
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。