Skip to content
Related Articles
Open in App
Not now

Related Articles

Count of Array elements in given range with remainder X when divided by K for Q queries

Improve Article
Save Article
  • Last Updated : 22 Apr, 2022
Improve Article
Save Article

Given an array arr[] of size N, an integer K and Q queries, each of form {x, l, r}. For each query, the task is to find the count of all elements in index range [l, r] which have remainder x when divided by K.

Examples:

Input: arr[] = {15, 28, 72, 43, 20, 0, 97}, K = 5, queries[] = {{3, 0, 3}, {0, 0, 6}, {6, 2, 4}}
Output: 2, 3, 0
Explanation: For the first query, there are 2 elements in the range [0, 3] whose remainder is 3 (28, 43). 
Similarly 3 elements in range [0, 6] whose remainder is 0 (15, 20, 0). 
In the third query, elements whose remainder are 6 should be found.
But for the given K = 5 possible remainders are only [0, 4]. So for any x >= K, answer will be 0.

Input: arr[] = {2, 4, 6, 7, 5}, K = 3, queries[] = {{2, 1, 4}}
Output: 1

 

Method 1: A simple approach is, for each query, iterate through l to r and count all elements whose remainder is x

Time Complexity: O(N * Q)
Auxiliary Space: O(1)

Method 2: This problem can also be solved with help of precalculation based on the following idea:

Precalculate what will be the remainder, when arr[i] is divided by K and store them in a matrix (say mat[]) where mat[i][j] represents the remainder of arr[j] is i when divided by K.
Now prefix sum of ith row of the matrix gives the count of elements which will have remainder i when divided by K. Therefore, after prefix sum mat[i][j] will represent total count of elements till jth index having remainder i when divided by K.
So for a query {x, l, r} the answer will be (mat[x][r] – mat[x][l] [+1 if arr[l]%K is x])

Follow the illustration below for a better understanding of the construction of the matrix.

Illustration:

Consider arr[] = {15, 28, 72, 43, 20, 0, 97}, K = 5

Make a 2D matrix named precompute, of size (K*N), and initialize it with 0. 
For the ith element, mark  precompute[arr[i]%K][i] = 1, do this for all i which states that the ith element has remainder arr[i]%K.

For the given example our precompute matrix will look like the following where row: remainder, column: index num.

  0 1 2 3 4 5 6
0 1 0 0 0 1 1 0
1 0 0 0 0 0 0 0
2 0 0 1 0 0 0 1
3 0 1 0 1 0 0 0
4 0 0 0 0 0 0 0

Then for each row calculate prefix sum. Now matrix will look like this:

  0 1 2 3 4 5 6
0 1 1 1 1 2 3 3
1 0 0 0 0 0 0 0
2 0 0 1 1 1 1 2
3 0 1 1 2 2 2 2
4 0 0 0 0 0 0 0

Here precompute[0][6] denotes that till 6th index there are a total of 3 elements which will have remainder 3 when divided by 5.

Follow the steps mentioned below to implement the idea:

  • Create the 2D array (say precompute).
  • Construct the array as mentioned above.
  • Traverse the queries:
    • For each query calculate the number of elements as per the formula shown above and store that in the answer array.
  • Return the array having the answers.

Note: This method is more efficient only when the number of queries is greater than K.

Below is the implementation of the above approach:

C++




// C++ program for the above approach
 
#include <bits/stdc++.h>
using namespace std;
const int MXN = 2e5;
int precompute[100][MXN];
 
// To precompute count prefix sum of all
// possible remainders
void precomputation(int arr[], int n, int k)
{
    // Mark cell whose remainder is arr[i]%k
    for (int i = 0; i < n; i++)
        precompute[arr[i] % k][i] = 1;
 
    // Take prefix sum for all rows
    for (int i = 0; i < k; i++) {
        for (int j = 1; j < n; j++) {
            precompute[i][j]
                += precompute[i][j - 1];
        }
    }
}
 
// Function to find the
// count of numbers for the queries
vector<int> findCount(int arr[], int K, int N,
                      vector<vector<int> >& queries)
{
    vector<int> res;
 
    // Initialise matrix with 0
    memset(precompute, 0, sizeof precompute);
 
    // To calculate count of remainders
    precomputation(arr, N, K);
    for (int i = 0; i < queries.size(); i++) {
        int x = queries[i][0];
        int l = queries[i][1];
        int r = queries[i][2];
        if (x >= K) {
            res.push_back(0);
            continue;
        }
        int count = precompute[x][r]
                    - precompute[x][l]
                    + (arr[l] % K == x);
        res.push_back(count);
    }
    return res;
}
 
// Driver code
int main()
{
    int arr[] = { 15, 28, 72, 43, 20, 0, 97 };
 
    int K = 5;
    int N = sizeof(arr) / sizeof(arr[0]);
    vector<vector<int> > queries{ { 3, 0, 3 },
                                  { 0, 0, 6 },
                                  { 6, 2, 4 } };
 
    vector<int> ans
        = findCount(arr, K, N, queries);
    for (int x : ans)
        cout << x << " ";
    return 0;
}


Java




// Java program for the above approach
import java.io.*;
import java.util.ArrayList;
 
class GFG {
 
  static int MXN = 200000;
  static int[][] precompute = new int[100][MXN];
 
  // To precompute count prefix sum of all
  // possible remainders
  static void precomputation(int[] arr, int n, int k)
  {
     
    // Mark cell whose remainder is arr[i]%k
    for (int i = 0; i < n; i++)
      precompute[arr[i] % k][i] = 1;
 
    // Take prefix sum for all rows
    for (int i = 0; i < k; i++) {
      for (int j = 1; j < n; j++) {
        precompute[i][j] += precompute[i][j - 1];
      }
    }
  }
 
  // Function to find the
  // count of numbers for the queries
  static ArrayList<Integer>
    findCount(int[] arr, int K, int N, int[][] queries)
  {
    ArrayList<Integer> res = new ArrayList<Integer>();
 
    // Initialise matrix with 0
    for (int i = 0; i < 100; i++) {
      for (int j = 0; j < MXN; j++)
        precompute[i][j] = 0;
    }
 
    // To calculate count of remainders
    precomputation(arr, N, K);
 
    for (int i = 0; i < queries.length; i++) {
      int x = queries[i][0];
      int l = queries[i][1];
      int r = queries[i][2];
      if (x >= K) {
        res.add(0);
        continue;
      }
      int count = precompute[x][r] - precompute[x][l]
        + ((arr[l] % K == x) ? 1 : 0);
      res.add(count);
    }
    return res;
  }
 
  // Driver code
  public static void main(String[] args)
  {
    int arr[] = { 15, 28, 72, 43, 20, 0, 97 };
 
    int K = 5;
    int N = arr.length;
    int[][] queries
      = { { 3, 0, 3 }, { 0, 0, 6 }, { 6, 2, 4 } };
 
    ArrayList<Integer> ans
      = findCount(arr, K, N, queries);
    for (int i = 0; i < ans.size(); i++)
      System.out.print(ans.get(i) + " ");
  }
}
 
// This code is contributed by phasing17


Python3




# python3 program for the above approach
MXN = int(2e5)
precompute = [[0 for _ in range(MXN)] for _ in range(100)]
 
# To precompute count prefix sum of all
# possible remainders
def precomputation(arr, n, k):
    global precompute
    # Mark cell whose remainder is arr[i]%k
    for i in range(0, n):
        precompute[arr[i] % k][i] = 1
 
        # Take prefix sum for all rows
    for i in range(0, k):
        for j in range(1, n):
            precompute[i][j] += precompute[i][j - 1]
 
# Function to find the
# count of numbers for the queries
def findCount(arr, K, N, queries):
    global precompute
    res = []
 
    # Initialise matrix with 0
 
    # To calculate count of remainders
    precomputation(arr, N, K)
    for i in range(0, len(queries)):
        x = queries[i][0]
        l = queries[i][1]
        r = queries[i][2]
        if (x >= K):
            res.append(0)
            continue
 
        count = precompute[x][r] - precompute[x][l] + (arr[l] % K == x)
        res.append(count)
 
    return res
 
# Driver code
if __name__ == "__main__":
 
    arr = [15, 28, 72, 43, 20, 0, 97]
 
    K = 5
    N = len(arr)
    queries = [[3, 0, 3],
               [0, 0, 6],
               [6, 2, 4]]
 
    ans = findCount(arr, K, N, queries)
    for x in ans:
        print(x, end=" ")
 
    # This code is contributed by rakeshsahni


C#




// C# code for the above discussed approach
using System;
using System.Collections;
 
public class GFG {
  static int MXN = 200000;
  static int[, ] precompute = new int[100, MXN];
 
  // To precompute count prefix sum of all
  // possible remainders
  static void precomputation(int[] arr, int n, int k)
  {
    // Mark cell whose remainder is arr[i]%k
    for (int i = 0; i < n; i++)
      precompute[arr[i] % k, i] = 1;
 
    // Take prefix sum for all rows
    for (int i = 0; i < k; i++) {
      for (int j = 1; j < n; j++) {
        precompute[i, j] += precompute[i, j - 1];
      }
    }
  }
 
  // Function to find the
  // count of numbers for the queries
  static ArrayList findCount(int[] arr, int K, int N,
                             int[, ] queries)
  {
    var res = new ArrayList();
 
    // Initialise matrix with 0
    for (int i = 0; i < 100; i++) {
      for (int j = 0; j < MXN; j++)
        precompute[i, j] = 0;
    }
 
    // To calculate count of remainders
    precomputation(arr, N, K);
 
    for (int i = 0; i < queries.GetLength(0); i++) {
      int x = queries[i, 0];
      int l = queries[i, 1];
      int r = queries[i, 2];
      if (x >= K) {
        res.Add(0);
        continue;
      }
      int count = precompute[x, r] - precompute[x, l]
        + ((arr[l] % K == x) ? 1 : 0);
      res.Add(count);
    }
    return res;
  }
 
  // Driver Code
  public static void Main(string[] args)
  {
    int[] arr = { 15, 28, 72, 43, 20, 0, 97 };
 
    int K = 5;
    int N = arr.Length;
    int[, ] queries
      = { { 3, 0, 3 }, { 0, 0, 6 }, { 6, 2, 4 } };
 
    ArrayList ans = findCount(arr, K, N, queries);
    for (int i = 0; i < ans.Count; i++)
      Console.Write(ans[i] + " ");
  }
}
 
// This code is contributed by phasing17


Javascript




<script>
        // JavaScript code for the above approach
        let MXN = 2e5;
        let precompute = new Array(100);
 
        for (let i = 0; i < precompute.length; i++) {
            precompute[i] = new Array(MXN).fill(0);
        }
 
        // To precompute count prefix sum of all
        // possible remainders
        function precomputation(arr, n, k)
        {
         
            // Mark cell whose remainder is arr[i]%k
            for (let i = 0; i < n; i++)
                precompute[arr[i] % k][i] = 1;
 
            // Take prefix sum for all rows
            for (let i = 0; i < k; i++) {
                for (let j = 1; j < n; j++) {
                    precompute[i][j]
                        += precompute[i][j - 1];
                }
            }
        }
 
        // Function to find the
        // count of numbers for the queries
        function findCount(arr, K, N, queries) {
            let res = [];
 
            // To calculate count of remainders
            precomputation(arr, N, K);
            for (let i = 0; i < queries.length; i++) {
                let x = queries[i][0];
                let l = queries[i][1];
                let r = queries[i][2];
                if (x >= K) {
                    res.push(0);
                    continue;
                }
                let count = precompute[x][r]
                    - precompute[x][l]
                    + (arr[l] % K == x);
                res.push(count);
            }
            return res;
        }
 
        // Driver code
        let arr = [15, 28, 72, 43, 20, 0, 97];
 
        let K = 5;
        let N = arr.length;
        let queries = [[3, 0, 3],
        [0, 0, 6],
        [6, 2, 4]];
 
        let ans
            = findCount(arr, K, N, queries);
        for (let x of ans)
            document.write(x + " ")
 
    // This code is contributed by Potta Lokesh
    </script>


Output

2 3 0 

Time Complexity: O(Q + K*N)
Auxiliary Space: O(K*N)


My Personal Notes arrow_drop_up
Related Articles

Start Your Coding Journey Now!