# Longest subsequence whose sum is divisible by a given number

• Difficulty Level : Hard
• Last Updated : 13 Aug, 2021

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:
Longest sub-sequence whose sum is
divisible by 3 is {3, 2, 1}
Input: arr[] = {2, 2}, M = 3
Output:

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`

## Javascript

 ``

Output:

`3`

Time Complexity: O(N * M)
Auxiliary Space: O(N * M).

My Personal Notes arrow_drop_up