Maximize occurrences of values between L and R on sequential addition of Array elements with modulo H

Given an array arr[] having N positive integers and a positive integers H, the task is to count the maximum occurrences of a value from the range [L, R] on adding arr[i] or arr[i] – 1 to X (initially 0). The integer X must be always be less than H. If it is greater than H, replace X by X % H
Examples: 
 

Input: arr = {16, 17, 14, 20, 20, 11, 22}, H = 24, L = 21, R = 23 
Output:
Explanation: 
Initially X = 0. 
Then add arr[0] – 1 to X, now the X is 15. This X is not good. 
Then add arr[1] – 1 to X, now the X is 15 + 16 = 31. 31 % H = 7. This X is also not good. 
Then add arr[2] to X, now the X is 7 + 14 = 21. This X is good. 
Then add arr[3] – 1 to X, now the X is (21 + 19) % H = 16. This X is not good. 
Then add arr[4] to X, now the X is (16 + 20) % H = 12. This X is not good. 
Then add arr[5] to X, now the X is 12 + 11 = 23. This X is good. 
Then add arr[6] to X, now the X is 23 + 22 = 21. This X is also good. 
So, the maximum number of good X in the example is 3.
Input: arr = {1, 2, 3}, H = 5, L = 1, R = 2 
Output:
 

 

Approach: This problem can be solved with dynamic programming. Maintain a table dp[N+1][H] which represents the maximum occurrences of an element in the range [L, R] on adding upto i elements. For every ith index, calculate the maximum possible frequency obtainable by adding arr[i] and arr[i] – 1. Once, computed for all indices, find the maximum from the last row of the dp[][] matrix. 
Below is the implementation of above approach: 
 

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ implementation of the
// above approach
#include <bits/stdc++.h>
using namespace std;
  
// Function that prints the number
// of times X gets a value
// between L and R
void goodInteger(int arr[], int n,
                 int h, int l, int r)
{
  
    vector<vector<int> > dp(
        n + 1,
        vector<int>(h, -1));
  
    // Base condition
    dp[0][0] = 0;
  
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < h; j++) {
  
            // Condition if X can be made
            // equal to j after i additions
            if (dp[i][j] != -1) {
  
                // Compute value of X
                // after adding arr[i]
                int h1 = (j + arr[i]) % h;
  
                // Compute value of X after
                // adding arr[i] - 1
                int h2 = (j + arr[i] - 1) % h;
  
                // Update dp as the maximum value
                dp[i + 1][h1]
                    = max(dp[i + 1][h1],
                          dp[i][j]
                              + (h1 >= l
                                 && h1 <= r));
                dp[i + 1][h2]
                    = max(dp[i + 1][h2],
                          dp[i][j]
                              + (h2 >= l
                                 && h2 <= r));
            }
        }
    }
  
    int ans = 0;
  
    // Compute maximum answer from all
    // possible cases
    for (int i = 0; i < h; i++) {
        if (dp[n][i] != -1)
            ans = max(ans, dp[n][i]);
    }
  
    // Printing maximum good occurrence of X
    cout << ans << "\n";
}
  
// Driver Code
int main()
{
  
    int A[] = { 16, 17, 14, 20, 20, 11, 22 };
    int H = 24;
    int L = 21;
    int R = 23;
  
    int size = sizeof(A) / sizeof(A[0]);
  
    goodInteger(A, size, H, L, R);
  
    return 0;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java implementation of the
// above approach
class GFG{
  
// Function that prints the number
// of times X gets a value
// between L and R
static void goodInteger(int arr[], int n,
                        int h, int l, int r)
{
    int [][]dp = new int[n + 1][h];
    for(int i = 0; i < n; i++) 
        for(int j = 0; j < h; j++) 
            dp[i][j] = -1;
              
    // Base condition
    dp[0][0] = 0;
  
    for(int i = 0; i < n; i++)
    {
        for(int j = 0; j < h; j++)
        {
  
            // Condition if X can be made
            // equal to j after i additions
            if (dp[i][j] != -1)
            {
  
                // Compute value of X
                // after adding arr[i]
                int h1 = (j + arr[i]) % h;
  
                // Compute value of X after
                // adding arr[i] - 1
                int h2 = (j + arr[i] - 1) % h;
  
                // Update dp as the maximum value
                dp[i + 1][h1] = Math.max(dp[i + 1][h1],
                                         dp[i][j] + 
                                        ((h1 >= l &&
                                          h1 <= r) ?
                                           1 : 0));
                dp[i + 1][h2] = Math.max(dp[i + 1][h2],
                                         dp[i][j] +
                                        ((h2 >= l &&
                                          h2 <= r) ? 
                                           1 : 0));
            }
        }
    }
    int ans = 0;
  
    // Compute maximum answer from all
    // possible cases
    for(int i = 0; i < h; i++)
    {
        if (dp[n][i] != -1)
            ans = Math.max(ans, dp[n][i]);
    }
  
    // Printing maximum good occurrence of X
    System.out.print(ans + "\n");
}
  
// Driver Code
public static void main(String[] args)
{
    int A[] = { 16, 17, 14, 20, 20, 11, 22 };
    int H = 24;
    int L = 21;
    int R = 23;
  
    int size = A.length;
  
    goodInteger(A, size, H, L, R);
}
}
  
// This code is contributed by 29AjayKumar

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python3 implementation of the above approach
  
# Function that prints the number
# of times X gets a value
# between L and R
def goodInteger(arr, n, h, l, r):
      
    dp = [[-1 for i in range(h)]
              for j in range(n + 1)]
  
    # Base condition
    dp[0][0] = 0
  
    for i in range(n):
        for j in range(h):
  
            # Condition if X can be made
            # equal to j after i additions
            if(dp[i][j] != -1):
  
                # Compute value of X
                # after adding arr[i]
                h1 = (j + arr[i]) % h
  
                # Compute value of X after
                # adding arr[i] - 1
                h2 = (j + arr[i] - 1) % h
  
                # Update dp as the maximum value
                dp[i + 1][h1] = max(dp[i + 1][h1],
                                    dp[i][j] + 
                                    (h1 >= l and h1 <= r))
  
                dp[i + 1][h2] = max(dp[i + 1][h2],
                                    dp[i][j] + 
                                    (h2 >= l and h2 <= r))
    ans = 0
  
    # Compute maximum answer from all
    # possible cases
    for i in range(h):
        if(dp[n][i] != -1):
            ans = max(ans, dp[n][i])
  
    # Printing maximum good occurrence of X
    print(ans)
  
# Driver Code
if __name__ == '__main__':
  
    A = [ 16, 17, 14, 20, 20, 11, 22 ]
    H = 24
    L = 21
    R = 23
  
    size = len(A)
    goodInteger(A, size, H, L, R)
  
# This code is contributed by Shivam Singh

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# implementation of the 
// above approach 
using System;
  
class GFG{ 
  
// Function that prints the number 
// of times X gets a value 
// between L and R 
static void goodint(int []arr, int n, 
                    int h, int l, int r) 
    int [,]dp = new int[n + 1, h]; 
  
    for(int i = 0; i < n; i++) 
        for(int j = 0; j < h; j++) 
            dp[i, j] = -1; 
              
    // Base condition 
    dp[0, 0] = 0; 
  
    for(int i = 0; i < n; i++) 
    
        for(int j = 0; j < h; j++) 
        
              
            // Condition if X can be made 
            // equal to j after i additions 
            if (dp[i, j] != -1) 
            
  
                // Compute value of X 
                // after adding arr[i] 
                int h1 = (j + arr[i]) % h; 
  
                // Compute value of X after 
                // adding arr[i] - 1 
                int h2 = (j + arr[i] - 1) % h; 
  
                // Update dp as the maximum value 
                dp[i + 1, h1] = Math.Max(dp[i + 1, h1], 
                                         dp[i, j] + 
                                        ((h1 >= l && 
                                          h1 <= r) ? 
                                           1 : 0)); 
                dp[i + 1, h2] = Math.Max(dp[i + 1, h2], 
                                         dp[i, j] + 
                                        ((h2 >= l && 
                                          h2 <= r) ? 
                                           1 : 0)); 
            
        
    
    int ans = 0; 
  
    // Compute maximum answer from all 
    // possible cases 
    for(int i = 0; i < h; i++) 
    
        if (dp[n, i] != -1) 
            ans = Math.Max(ans, dp[n, i]); 
    
  
    // Printing maximum good occurrence of X 
    Console.Write(ans + "\n"); 
  
// Driver Code 
public static void Main(String[] args) 
    int []A = { 16, 17, 14, 20, 20, 11, 22 }; 
    int H = 24; 
    int L = 21; 
    int R = 23; 
  
    int size = A.Length; 
  
    goodint(A, size, H, L, R); 
  
// This code is contributed by Rajput-Ji

chevron_right


Output: 

3

 

Time Complexity: O(N * H)
 

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.