Check if any valid sequence is divisible by M

Given an array of N integers, using ‘+’ and ‘-‘ between the elements check if there is a way to form a sequence of numbers which evaluate to a number divisible by M

Examples:

Input : arr = {1, 2, 3, 4, 6}
        M = 4
Output : True, 
There is a valid sequence i. e., (1 - 2
+ 3 + 4 + 6), which evaluates to 12 that
is divisible by 4 

Input : arr = {1, 3, 9}
        M = 2
Output : False
There is no sequence which evaluates to
a number divisible by M.



A simple solution is to recursively consider all possible scenarios ie either use a ;+’ or a ‘-‘ operator between the elements and maintain a variable sum which stores the result.If this result is divisible by M then return true else return false
Recursive implementation is as follows:

bool isPossible(int index, int sum)
{
    // Base case
    if (index == n) {
  
        // check if sum is divisible by M
        if ((sum % M) == 0)
            return true;
        return false;
    }

    // recursively call by considering '+' 
    // or '-' between index and index+1

    // 1.Try placing '+'
    bool placeAdd = isPossible(index + 1, 
                        sum + arr[index]);

    // 2. Try placing '-'
    bool placeMinus = isPossible(index + 1, 
                         sum - arr[index]);

    if (placeAdd || placeMinus) 
        return true;
    
    return false;
}

There are overlapping subproblems as shown in the image below (Note: the image represents the recursion tree till index = 3)

Recursion Tree till index = 3

So, now we will solve this using dynamic programming



Method 1:
We apply Dynamic Programming with two states :-
(i) index,
(ii) sum
So DP[index][sum] stores the current index we are at and sum stores the result of evaluation of the sequence formed till that index.

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

const int MAX = 1000;

bool isPossible(int n, int index, int sum, 
          int M, int arr[], int dp[][MAX])
{

    // Base case
    if (index == n) {

        // check if sum is divisible by M
        if ((sum % M) == 0)
            return true;
        return false;
    }

    // check if the current state 
    // is already computed
    if (dp[index][sum] != -1) 
        return dp[index][sum];
    
    // 1.Try placing '+'
    bool placeAdd = isPossible(n, index + 1, 
               sum + arr[index], M, arr, dp);

    // 2. Try placing '-'
    bool placeMinus = isPossible(n, index + 1, 
                sum - arr[index], M, arr, dp);

    // calculate value of res for recursive case
    bool res = (placeAdd || placeMinus);

    // store the value for res for current 
    // states and return for parent call
    dp[index][sum] = res;
    return res;
}
int main()
{
    int arr[] = { 1, 2, 3, 4, 6 };
    int n = sizeof(arr)/sizeof(arr[0]);
    int M = 4;

    int dp[n + 1][MAX];
    memset(dp, -1, sizeof(dp));

    bool res;
    res = isPossible(n, 0, 0, M, arr, dp);

    cout << (res ? "True" : "False") << endl;
    return 0;
}
Output:

True

The Complexity of this method is O(N*sum) where sum is the maximum possible sum for the sequence of integers and N is the number of elements in the array.

Method 2(efficient):
This is more efficient than Method 1. Here also, we apply Dynamic Programming but with two different states :-
(i) index,
(ii) modulo
So DP[index][modulo] stores the modulus of the result of evaluation of the sequence formed till that index, with M.

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

const int MAX = 100;

int isPossible(int n, int index, int modulo,
            int M, int arr[], int dp[][MAX])
{
    // Calculate modulo for this call
    modulo = ((modulo % M) + M) % M;

    // Base case
    if (index == n) {

        // check if sum is divisible by M
        if (modulo == 0)
            return 1;
        return 0;
    }

    // check if the current state is 
    // already computed
    if (dp[index][modulo] != -1) 
        return dp[index][modulo];

    // 1.Try placing '+'
    int placeAdd = isPossible(n, index + 1,
            modulo + arr[index], M, arr, dp);

    // 2. Try placing '-'
    int placeMinus = isPossible(n, index + 1, 
            modulo - arr[index], M, arr, dp);

    // calculate value of res for recursive
    // case
    bool res = (placeAdd || placeMinus);

    // store the value for res for current 
    // states and return for parent call
    dp[index][modulo] = res;
    return res;
}

int main()
{
    int arr[] = { 1, 2, 3, 4, 6 };
    int n = sizeof(arr)/sizeof(arr[0]);
    int M = 4;

    // MAX is the Maximum value M can take
    int dp[n + 1][MAX];
    memset(dp, -1, sizeof(dp));

    bool res;
    res = isPossible(n, 1, arr[0], M, arr, dp);

    cout << (res ? "True" : "False") << endl;
    return 0;
}
Output:

True

The Complexity of this method is O(N*M).



My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.




Recommended Posts:



2.9 Average Difficulty : 2.9/5.0
Based on 13 vote(s)






User Actions