# Check if any valid sequence is divisible by M

A sequence is a collection of objects, and in our case, it is a collection of integers. The task is to find if a sequence with the usage of the addition and subtraction operator within the elements is divisible by M or not.

## Problem Statement

Given an integer M and an array of integers. Using only addition and subtraction between elements check if there is a valid sequence whose solution is divisible by M.

### Sample Example 1

Input: M = 2, arr = {1, 2, 5}

Output: TRUE


Explanation − For the given array a valid sequence {1 + 2 + 5} = {8} is possible which is divisible by 2.

### Sample Example 2

Input: M = 4, arr = {1, 2}

Output: FALSE


Explanation − For the given array no sequence is possible whose solution is divisible by 4.

## Approach 1: Brute Force Approach

A simple solution to the problem is to find all the possible sequences of the array using a recursive function and then check if any sequence is divisible by M.

### Pseudocode

procedure divisible (M, arr[], index, sum, n)
if index == n
if sum is a multiple of M
ans = TRUE
end if
ans = false
end if
divisible(M, arr, index + 1, sum + arr[index], n) or divisible(M, arr, index + 1, sum - arr[index], n)
end procedure


### Example: C++ Implementation

In the following program, we use a recursive approach to find all the valid sequences and then check if any valid sequence is divisible by M.

#include <bits/stdc++.h>
using namespace std;

// Recusive function to find if a valid sequence is divisible by M or not
bool divisible(int M, int arr[], int index, int sum, int n){

// Cheking the divisiblilty by M when the array ends
if (index == n)  {
if (sum % M == 0){
return true;
}
return false;
}

// If either of addition or subtraction is true, return true
return divisible(M, arr, index + 1, sum + arr[index], n) || divisible(M, arr, index + 1, sum - arr[index], n);
}
int main(){
int M = 4, arr[2] = {1, 5};
if (divisible(M, arr, 0, 0, 2)){
cout << "TRUE";
}
else{
cout << " FALSE";
}
return 0;
}


### Output

TRUE


Time Complexity − O(2^n) due to use of recursion.

Space Complexity − O(n) due to the recursive stack space.

## Approach 2: Backtracking

This approach is similar to the previous brute force recursive approach except that using backtracking we can backtrack the search space to not go on a path that we know does not have a valid sequence divisible by M.

### Pseudocode

procedure divisible (M, arr[], index, sum, n)
if index == n
if sum is a multiple of M
ans = TRUE
end if
ans = false
end if
if divisible(M, arr, index + 1, sum + arr[index], n)
ans = true
end if
if divisible(M, arr, index + 1, sum - arr[index], n)
ans = true
end if
ans = false
end procedure


### Example: C++ Implementation

In the following program, we prune the search space using backtracking to find the solution to the problem.

#include <bits/stdc++.h>
using namespace std;

// Function to find if a valid sequence is divisible by M or not
bool divisible(int M, int arr[], int index, int sum, int n){

// Cheking the divisiblilty by M when the array ends
if (index == n){
if (sum % M == 0){
return true;
}
return false;
}

// Checking the divisibility of sum + arr[index]
if (divisible(M, arr, index + 1, sum + arr[index], n)){
return true;
}

// Checking the divisibility of sum - arr[index]
if (divisible(M, arr, index + 1, sum - arr[index], n)){
return true;
}
return false;
}
int main(){
int M = 4, arr[2] = {1, 5};
if (divisible(M, arr, 0, 0, 2)){
cout << "TRUE";
}
else{
cout << " FALSE";
}
return 0;
}


### Output

TRUE


Time Complexity − O(2^n) for worst case scenario but in practise it is better than brute force approach due to pruning of search space.

Space Complexity − O(n) due to recursive stack space.

## Approach 3: Greedy Approach

A greedy solution to the problem is to first sort array in increasing order and then greedily applying addition function if the sum does not exceed M. This approach may not give the global optimal solution but gives the local optimal solution.

### Pseudocode

procedure divisible (M, arr[])
sum = 0
for i = 1 to end of arr
sum = sum + arr[i]
if sum is divisible by M
ans = true
end if
sort array arr[]
i = 0
j = last index of array
while i < j
if arr[j] - arr[i] is divisible by M
ans = true
end if
if sum % M == (sum - arr[j]) % M
sum = sum - arr[j]
j = j - 1
else
sum = sum - arr[i]
i = i + 1
end if
ans = false
end procedure


### Example: C++ Implemenation

In the following program, array is sorted to find optimal local subarray divisible by M.

#include <bits/stdc++.h>
using namespace std;

// Greedy function to find if a valid sequence is divisible by M or not
bool divisible(int M, vector<int> &arr){
int sum = 0;
for (int i = 0; i < arr.size(); i++) {
sum += arr[i];
}

// Checking if sumof all elements is divisible by M
if (sum % M == 0){
return true;
}

sort(arr.begin(), arr.end());
int i = 0, j = arr.size() - 1;
while (i < j){

// Checking if the difference between the largest and smallest element at a time in the array is divisible by M
if ((arr[j] - arr[i]) % M == 0){
return true;
}

// Removing either the largest or smallest element based on which does not affect the sum's divisibility
if (sum % M == (sum - arr[i]) % M){
sum -= arr[i];
i++;
}
else{
sum -= arr[j];
j--;
}
}
return false;
}
int main(){
int M = 4;
int array[2] = {1, 3};
vector<int> arr(array, array + 2);
if (divisible(M, arr)){
cout << "TRUE";
}
else{
cout << " FALSE";
}
return 0;
}


### Output

TRUE


## Approach 4: Dynamic Programming

Using the concept of dynamic programming, in this solution we store the intermediate results of evaluation. We’ll create a table with N+1 rows and M columns and the base case where result % M == 0 when we use no element of array. Then iterating over all possible remainders of modulo M, we update the table.

### Pseudocode

procedure divisible (arr[], M , N)
dp[N+1][M] = false
dp[0][0] = true
for i = 1 to N
for i = j to M
mod = arr[ i- 1] % M
dp[i][j] = dp[i - 1][(j - mod + M) % M] or dp[i - 1][(j + mod) % M]
ans = dp[N][0]
end procedure


### Example: C++ Implementation

In the following program we split the problem in subprobles and then solve them.

#include <bits/stdc++.h>
using namespace std;

// Function to find if a valid sequence is divisible by M or not
bool divisible(int arr[], int M, int N){

// Creating the dp table of size N+1 * M
vector<vector<bool> > dp(N + 1, vector<bool>(M, false));

// Base case
dp[0][0] = true;

// For each element iterating over all possible remainders j modulo M
for (int i = 1; i <= N; i++){
for (int j = 0; j < M; j++){
int mod = arr[i - 1] % M;

// Either exclude or include the current element in the table
dp[i][j] = dp[i - 1][(j - mod + M) % M] || dp[i - 1][(j + mod) % M];
}
}
return dp[N][0];
}
int main(){
int M = 4;
int arr[2] = {1, 3};
if (divisible(arr, M, 2)){
cout << "TRUE";
}
else{
cout << " FALSE";
}
return 0;
}


### Output

TRUE


## Conclusion

In conclusion, for finding a valid sequence divisible by M, we can apply multiple approaches with varying tiem and space analysis ranging from O(2^n) in the case of brute force to O(NM) in the case of dynamic programming which is the most efficient approach.

Updated on: 25-Jul-2023

61 Views