Maximum count of values of S modulo M lying in a range [L, R] after performing given operations on the array

Given an array arr[] of N integers along with integers M, L, R. Consider a variable S(initially 0). The task is to find the maximum count of values of S % M that lies in the range [L, R] after performing the following operations for each element in the given array:

  • Add arr[i] or arr[i] – 1 to S.
  • Change S to S % M.

Examples: 

Input: arr[] = {17, 11, 10, 8, 15}, M = 22, L = 14, R = 16
Output: 3
Explanation:
Initially S = 0, 
Step 1: Choose, arr[0] – 1 = 16 and add it to S = 16 and S%M = 16. Therefore, count = 1
Step 2: Choose, arr[1] = 11 and add it to S = 16 + 11 = 27 and S%M = 5. Therefore, count = 1
Step 3: Choose, arr[2] = 10 and add it to S = 16 + 10 +11 = 37 and S%M = 15. Therefore, count = 2
Step 4: Choose, arr[3] = 8 and add it to S = 16 + 10 + 11 + 8 = 45 and S%M = 1. Therefore, count = 2
Step 5: Choose, arr[4] = 15 and add it to S = 16 + 10 + 11 + 8 + 15 = 60 and S%M = 16. Therefore, count = 3.
Hence the maximum count is 3.

Input: arr[] = {23, 1}, M = 24, L = 21, R = 23
Output: 2

Naive Approach: The simplest approach is to traverse the given array arr[] and add arr[i] or arr[i – 1] to the given S and check if S%M lies in the range [L, R] or not. Since there are two possibilities to choose the given numbers. Therefore, use recursion to recursively get the maximum count of values of S%M lies in the range [L, R].

Time Complexity: O(2N)
Auxiliary Space: O(N)

Efficient Approach: To optimize the above approach the idea is to use Dynamic Programming to store the overlapping subproblems and then find the maximum count of S%M lies in the range [L, R]. Follow the steps below to solve the problem:

  1. Initialize a unordered_map dp to store the values of states that have overlapping subproblems.
  2. Initialize the sum to be 0, and then recursively add arr[i] or arr[i] – 1 value to the sum S.
  3. At every step, check whether the S%M lies in the range [L, R] or not. If it lies in the range then count that value and update this current state in the above map dp as 1. Else update as 0.
  4. After looking out for all possible combinations, return the count of values of S%M that lies in the range [L, R].

Below is the implementation of the above approach:

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ program for the above approach
  
#include <bits/stdc++.h>
using namespace std;
  
// Lookup table
map<pair<int, int>, int> dp;
  
// Function to count the value of S
// after adding arr[i] or arr[i - 1]
// to the sum S at each time
int countMagicNumbers(int idx, int sum,
                      int a[], int n,
                      int m, int l, int r)
{
    // Base Case
    if (idx == n) {
  
        // Store the mod value
        int temp = sum % m;
  
        // If the mod value lies in
        // the range then return 1
        if (temp == l || temp == r
            || (temp > l && temp < r))
            return dp[{ idx, sum }] = 1;
  
        // Else return 0
        else
            return dp[{ idx, sum }] = 0;
    }
  
    // Store the current state
    pair<int, int> curr
        = make_pair(idx, sum);
  
    // If already computed, return the
    // computed value
    if (dp.find(curr) != dp.end())
        return dp[curr];
  
    // Recursively adding the elements
    // to the sum adding ai value
    int ls = countMagicNumbers(idx + 1,
                               sum + a[idx],
                               a, n,
                               m, l, r);
  
    // Adding arr[i] - 1 value
    int rs = countMagicNumbers(idx + 1,
                               sum + (a[idx] - 1),
                               a, n, m, l, r);
  
    // Return the maximum count to
    // check for root value as well
    int temp1 = max(ls, rs);
    int temp = sum % m;
  
    // Avoid counting idx = 0 as possible
    // solution we are using idx != 0
    if ((temp == l || temp == r
         || (temp > l && temp < r))
        && idx != 0) {
        temp1 += 1;
    }
  
    // Return the value of current state
    return dp[{ idx, sum }] = temp1;
}
  
// Driver Code
int main()
{
    int N = 5, M = 22, L = 14, R = 16;
    int arr[] = { 17, 11, 10, 8, 15 };
  
    cout << countMagicNumbers(0, 0, arr,
                              N, M, L, R);
  
    return 0;
}

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python3 program for the above approach
  
# Lookup table
dp = {}
  
# Function to count the value of S
# after adding arr[i] or arr[i - 1]
# to the sum S at each time
def countMagicNumbers(idx, sum, a, n, m, l, r):
      
    # Base Case
    if (idx == n):
  
        # Store the mod value
        temp = sum % m
  
        # If the mod value lies in
        # the range then return 1
        if (temp == l or temp == r or 
           (temp > l and temp < r)):
            dp[(idx, sum)] = 1
            return dp[(idx, sum)]
  
        # Else return 0
        else:
            dp[(idx, sum)] = 0
            return dp[(idx, sum)]
  
    # Store the current state
    curr = (idx, sum)
  
    # If already computed, return the
    # computed value
    if (curr in dp):
        return dp[curr]
  
    # Recursively adding the elements
    # to the sum adding ai value
    ls = countMagicNumbers(idx + 1,
                           sum + a[idx],
                           a, n, m, l, r)
  
    # Adding arr[i] - 1 value
    rs = countMagicNumbers(idx + 1,
                           sum + (a[idx] - 1),
                           a, n, m, l, r)
  
    # Return the maximum count to
    # check for root value as well
    temp1 = max(ls, rs)
    temp = sum % m
  
    # Avoid counting idx = 0 as possible
    # solution we are using idx != 0
    if ((temp == l or temp == r or
        (temp > l and temp < r)) and 
         idx != 0):
        temp1 += 1
  
    # Return the value of current state
    dp[(idx, sum)] = temp1
    return dp[(idx, sum)]
  
# Driver Code
if __name__ == '__main__':
      
    N = 5
    M = 22
    L = 14
    R = 16
      
    arr = [ 17, 11, 10, 8, 15 ]
  
    print(countMagicNumbers(0, 0, arr, N, M, L, R))
  
# This code is contributed by mohit kumar 29

chevron_right


Output: 

3

Time Complexity: O(S*N), where N is the size of the given array, and S is the sum of all array elements.
Space Complexity: O(S*N)

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

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 Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.



Improved By : mohit kumar 29