Related Articles
Longest subsequence whose sum is divisible by a given number
• Difficulty Level : Hard
• Last Updated : 07 Nov, 2019

Given an array arr[] and an integer M, the task is to find the length of the longest subsequence whose sum is divisible by M. If there is no such sub-sequence then print 0.

Examples:

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

## Recommended: Please try your approach on {IDE} first, before moving on to the solution.

Approach: A simple way to solve this will be to generate all the possible sub-sequences and then find the largest among them divisible whose sum is divisible by M. However, for smaller values of M, a dynamic programming based approach can be used.
Let’s look at the recurrence relation first.

dp[i][curr_mod] = max(dp[i + 1][curr_mod], dp[i + 1][(curr_mod + arr[i]) % m] + 1)

Let’s understand the states of DP now. Here, dp[i][curr_mod] stores the longest subsequence of subarray arr[i…N-1] such that the sum of this subsequence and curr_mod is divisible by M. At each step, either index i can be chosen updating curr_mod or it can be ignored.

Also, note that only SUM % m needs to be stored instead of the entire sum as this information is sufficient to complete the states of DP.

Below is the implementation of the above approach:

## 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 `

Output:

```3
```

Time Complexity: O(N * M)

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.

My Personal Notes arrow_drop_up
Recommended Articles
Page :