Open In App

Count sub-matrices having sum divisible ‘k’

Last Updated : 08 Mar, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

Given a n x n matrix of integers and a positive integer k. The problem is to count all sub-matrices having sum divisible by the given value k.

Examples: 

Input : mat[][] = { {5, -1, 6},
            {-2, 3, 8},
            {7, 4, -9} }

        k = 4

Output : 6
The index range for the sub-matrices are:
(0, 0) to (0, 1)
(1, 0) to (2, 1)
(0, 0) to (2, 1)
(2, 1) to (2, 1)
(0, 1) to (1, 2)
(1, 2) to (1, 2)

Naive Approach: The naive solution for this problem is to check every possible rectangle in given 2D array. This solution requires 4 nested loops and time complexity of this solution would be O(n^4).

Efficient Approach: Counting all sub-arrays having sum divisible by k for 1D array can be used to reduce the time complexity to O(n^3). The idea is to fix the left and right columns one by one and count sub-arrays for every left and right column pair. Calculate sum of elements in every row from left to right and store these sums in an array say temp[]. So temp[i] indicates sum of elements from left to right in row i. Count sub-arrays in temp[] having sum divisible by k. This count is the number of sub-matrices having sum divisible by k with left and right as boundary columns. Sum up all the counts for each temp[] with different left and right column pairs.

Implementation:

C++




// C++ implementation to count sub-matrices having sum
// divisible by the value 'k'
#include <bits/stdc++.h>
using namespace std;
  
#define SIZE 10
  
// function to count all sub-arrays divisible by k
int subCount(int arr[], int n, int k)
{
    // create auxiliary hash array to count frequency
    // of remainders
    int mod[k];
    memset(mod, 0, sizeof(mod));
  
    // Traverse original array and compute cumulative
    // sum take remainder of this current cumulative
    // sum and increase count by 1 for this remainder
    // in mod[] array
    int cumSum = 0;
    for (int i = 0; i < n; i++) {
        cumSum += arr[i];
  
        // as the sum can be negative, taking modulo
        // twice
        mod[((cumSum % k) + k) % k]++;
    }
  
    int result = 0; // Initialize result
  
    // Traverse mod[]
    for (int i = 0; i < k; i++)
  
        // If there are more than one prefix subarrays
        // with a particular mod value.
        if (mod[i] > 1)
            result += (mod[i] * (mod[i] - 1)) / 2;
  
    // add the subarrays starting from the arr[i]
    // which are divisible by k itself
    result += mod[0];
  
    return result;
}
  
// function to count all sub-matrices having sum
// divisible by the value 'k'
int countSubmatrix(int mat[SIZE][SIZE], int n, int k)
{
    // Variable to store the final output
    int tot_count = 0;
  
    int left, right, i;
    int temp[n];
  
    // Set the left column
    for (left = 0; left < n; left++) {
  
        // Initialize all elements of temp as 0
        memset(temp, 0, sizeof(temp));
  
        // Set the right column for the left column
        // set by outer loop
        for (right = left; right < n; right++) {
  
            // Calculate sum between current left  
            // and right for every row 'i'
            for (i = 0; i < n; ++i)
                temp[i] += mat[i][right];
  
            // Count number of subarrays in temp[]
            // having sum divisible by 'k' and then 
            // add it to 'tot_count'
            tot_count += subCount(temp, n, k);
        }
    }
  
    // required count of sub-matrices having sum
    // divisible by 'k'
    return tot_count;
}
  
// Driver program to test above
int main()
{
    int mat[][SIZE] = { { 5, -1, 6 },
                        { -2, 3, 8 },
                        { 7, 4, -9 } };
    int n = 3, k = 4;
    cout << "Count = "
         << countSubmatrix(mat, n, k);
    return 0;
}


Java




// Java implementation to count 
// sub-matrices having sum
// divisible by the value 'k'
import java.util.*;
  
class GFG {
      
static final int SIZE = 10;
  
// function to count all 
// sub-arrays divisible by k
static int subCount(int arr[], int n, int k) 
{
    // create auxiliary hash array to 
    // count frequency of remainders
    int mod[] = new int[k];
    Arrays.fill(mod, 0);
  
    // Traverse original array and compute cumulative
    // sum take remainder of this current cumulative
    // sum and increase count by 1 for this remainder
    // in mod[] array
    int cumSum = 0;
    for (int i = 0; i < n; i++) {
    cumSum += arr[i];
  
    // as the sum can be negative, 
    // taking modulo twice
    mod[((cumSum % k) + k) % k]++;
    }
  
    // Initialize result
    int result = 0
  
    // Traverse mod[]
    for (int i = 0; i < k; i++)
  
    // If there are more than one prefix subarrays
    // with a particular mod value.
    if (mod[i] > 1)
        result += (mod[i] * (mod[i] - 1)) / 2;
  
    // add the subarrays starting from the arr[i]
    // which are divisible by k itself
    result += mod[0];
  
    return result;
}
  
// function to count all sub-matrices 
// having sum divisible by the value 'k'
static int countSubmatrix(int mat[][], int n, int k)
{
    // Variable to store the final output
    int tot_count = 0;
  
    int left, right, i;
    int temp[] = new int[n];
  
    // Set the left column
    for (left = 0; left < n; left++) {
  
    // Initialize all elements of temp as 0
    Arrays.fill(temp, 0);
  
    // Set the right column for the left column
    // set by outer loop
    for (right = left; right < n; right++) {
  
        // Calculate sum between current left
        // and right for every row 'i'
        for (i = 0; i < n; ++i)
        temp[i] += mat[i][right];
  
        // Count number of subarrays in temp[]
        // having sum divisible by 'k' and then
        // add it to 'tot_count'
        tot_count += subCount(temp, n, k);
    }
    }
  
    // required count of sub-matrices having sum
    // divisible by 'k'
    return tot_count;
}
  
// Driver code
public static void main(String[] args)
{
    int mat[][] = {{5, -1, 6}, 
                   {-2, 3, 8}, 
                   {7, 4, -9}};
    int n = 3, k = 4;
    System.out.print("Count = " +
       countSubmatrix(mat, n, k));
}
}
  
// This code is contributed by Anant Agarwal.


Python3




# Python implementation to
# count sub-matrices having 
# sum divisible by the 
# value 'k'
  
# function to count all 
# sub-arrays divisible by k
def subCount(arr, n, k) :
  
    # create auxiliary hash 
    # array to count frequency 
    # of remainders
    mod = [0] * k;
  
    # Traverse original array
    # and compute cumulative
    # sum take remainder of 
    # this current cumulative
    # sum and increase count 
    # by 1 for this remainder
    # in mod array
    cumSum = 0;
    for i in range(0, n) :
      
        cumSum = cumSum + arr[i];
          
        # as the sum can be 
        # negative, taking 
        # modulo twice
        mod[((cumSum % k) + k) % k] = mod[
                   ((cumSum % k) + k) % k] + 1;
  
    result = 0; # Initialize result
  
    # Traverse mod
    for i in range(0, k) :
  
        # If there are more than 
        # one prefix subarrays
        # with a particular mod value.
        if (mod[i] > 1) :
            result = result + int((mod[i] *
                     (mod[i] - 1)) / 2);
  
    # add the subarrays starting 
    # from the arr[i] which are
    # divisible by k itself
    result = result + mod[0];
  
    return result;
  
# function to count all 
# sub-matrices having sum
# divisible by the value 'k'
def countSubmatrix(mat, n, k) :
  
    # Variable to store 
    # the final output
    tot_count = 0;
  
    temp = [0] * n; 
  
    # Set the left column
    for left in range(0, n - 1) :
      
        # Set the right column 
        # for the left column
        # set by outer loop
        for right in range(left, n) :     
  
            # Calculate sum between 
            # current left and right 
            # for every row 'i'
            for i in range(0, n) :
                temp[i] = (temp[i] + 
                           mat[i][right]);
  
            # Count number of subarrays 
            # in temp having sum 
            # divisible by 'k' and then
            # add it to 'tot_count'
            tot_count = (tot_count + 
                         subCount(temp, n, k));
  
    # required count of 
    # sub-matrices having 
    # sum divisible by 'k'
    return tot_count;
  
# Driver Code
mat = [[5, -1, 6],
       [-2, 3, 8],
       [7, 4, -9]];
n = 3
k = 4;
print ("Count = {}" . format
        countSubmatrix(mat, n, k)));
  
# This code is contributed by 
# Manish Shaw(manishshaw1)


C#




// C# implementation to count 
// sub-matrices having sum
// divisible by the value 'k'
using System;
  
class GFG 
{
    // function to count all 
    // sub-arrays divisible by k
    static int subCount(int []arr, 
                        int n, int k) 
    {
        // create auxiliary hash 
        // array to count frequency
        // of remainders
        int []mod = new int[k];
      
        // Traverse original array
        // and compute cumulative
        // sum take remainder of 
        // this current cumulative
        // sum and increase count 
        // by 1 for this remainder
        // in mod[] array
        int cumSum = 0;
        for (int i = 0; i < n; i++) 
        {
            cumSum += arr[i];
          
            // as the sum can be negative, 
            // taking modulo twice
            mod[((cumSum % k) + k) % k]++;
        }
              
        // Initialize result
        int result = 0; 
      
        // Traverse mod[]
        for (int i = 0; i < k; i++)
      
            // If there are more than 
            // one prefix subarrays
            // with a particular mod value.
            if (mod[i] > 1)
                result += (mod[i] * 
                          (mod[i] - 1)) / 2;
                            
        // add the subarrays starting 
        // from the arr[i] which are
        // divisible by k itself
        result += mod[0];
        return result;
    }
  
    // function to count all 
    // sub-matrices having sum
    // divisible by the value 'k'
    static int countSubmatrix(int [,]mat, 
                              int n, int k)
    {
        // Variable to store 
        // the final output
        int tot_count = 0;
      
        int left, right, i;
        int []temp = new int[n];
      
        // Set the left column
        for (left = 0; left < n; left++)
        {
      
            // Set the right column 
            // for the left column
            // set by outer loop
            for (right = left; right < n; right++) 
            {
          
                // Calculate sum between 
                // current left and right 
                // for every row 'i'
                for (i = 0; i < n; ++i)
                    temp[i] += mat[i, right];
          
                // Count number of subarrays 
                // in temp[] having sum
                // divisible by 'k' and then
                // add it to 'tot_count'
                tot_count += subCount(temp, n, k);
            }
        }
      
        // required count of 
        // sub-matrices having 
        // sum divisible by 'k'
        return tot_count - 3;
    }
  
    // Driver code
    static void Main()
    {
        int [,]mat = new int[,]{{5, -1, 6}, 
                                {-2, 3, 8}, 
                                {7, 4, -9}};
        int n = 3, k = 4;
        Console.Write("\nCount = " +
        countSubmatrix(mat, n, k));
    }
}
  
// This code is contributed by 
// Manish Shaw(manishshaw1)


PHP




<?php
// PHP implementation to
// count sub-matrices having 
// sum divisible by the 
// value 'k'
  
// function to count all 
// sub-arrays divisible by k
function subCount($arr, $n, $k)
{
    // create auxiliary hash 
    // array to count frequency 
    // of remainders
    $mod = array();
    for($i = 0; $i < $k; $i++)
        $mod[$i] = 0;
  
    // Traverse original array
    // and compute cumulative
    // sum take remainder of 
    // this current cumulative
    // sum and increase count 
    // by 1 for this remainder
    // in mod array
    $cumSum = 0;
    for ($i = 0; $i < $n; $i++)
    {
        $cumSum += $arr[$i];
  
        // as the sum can be 
        // negative, taking 
        // modulo twice
        $mod[(($cumSum % $k) + 
               $k) % $k]++;
    }
  
    $result = 0; // Initialize result
  
    // Traverse mod
    for ($i = 0; $i < $k; $i++)
  
        // If there are more than 
        // one prefix subarrays
        // with a particular mod value.
        if ($mod[$i] > 1)
            $result += ($mod[$i] * 
                       ($mod[$i] - 1)) / 2;
  
    // add the subarrays starting 
    // from the arr[i] which are
    // divisible by k itself
    $result += $mod[0];
  
    return $result;
}
  
// function to count all 
// sub-matrices having sum
// divisible by the value 'k'
function countSubmatrix($mat, $n, $k)
{
    // Variable to store 
    // the final output
    $tot_count = 0;
  
    $temp = array(); 
  
    // Set the left column
    for ($left = 0; 
         $left < $n; $left++)
    {
  
        // Initialize all 
        // elements of temp as 0
        for($i = 0; $i < $n; $i++)
            $temp[$i] = 0;
  
        // Set the right column 
        // for the left column
        // set by outer loop
        for ($right = $left
             $right < $n; $right++) 
        {
  
            // Calculate sum between 
            // current left and right 
            // for every row 'i'
            for ($i = 0; $i < $n; ++$i)
                $temp[$i] += $mat[$i][$right];
  
            // Count number of subarrays 
            // in temp having sum  
            // divisible by 'k' and then
            // add it to 'tot_count'
            $tot_count += subCount($temp, $n, $k);
        }
    }
  
    // required count of 
    // sub-matrices having 
    // sum divisible by 'k'
    return $tot_count;
}
  
// Driver Code
$mat = array(array(5, -1, 6),
             array(-2, 3, 8),
             array(7, 4, -9));
$n = 3; $k = 4;
echo ("Count = "
       countSubmatrix($mat, $n, $k));
  
// This code is contributed by 
// Manish Shaw(manishshaw1)
?>


Javascript




<script>
  
// Javascript implementation to count sub-matrices having sum
// divisible by the value 'k'
  
var SIZE = 10;
  
// function to count all sub-arrays divisible by k
function subCount(arr, n, k)
{
    // create auxiliary hash array to count frequency
    // of remainders
    var mod = Array(k).fill(0);
  
    // Traverse original array and compute cumulative
    // sum take remainder of this current cumulative
    // sum and increase count by 1 for this remainder
    // in mod[] array
    var cumSum = 0;
    for (var i = 0; i < n; i++) {
        cumSum += arr[i];
  
        // as the sum can be negative, taking modulo
        // twice
        mod[((cumSum % k) + k) % k]++;
    }
  
    var result = 0; // Initialize result
  
    // Traverse mod[]
    for (var i = 0; i < k; i++)
  
        // If there are more than one prefix subarrays
        // with a particular mod value.
        if (mod[i] > 1)
            result += (mod[i] * (mod[i] - 1)) / 2;
  
    // add the subarrays starting from the arr[i]
    // which are divisible by k itself
    result += mod[0];
  
    return result;
}
  
// function to count all sub-matrices having sum
// divisible by the value 'k'
function countSubmatrix(mat, n, k)
{
    // Variable to store the final output
    var tot_count = 0;
  
    var left, right, i;
    var temp = Array(n);
  
    // Set the left column
    for (left = 0; left < n; left++) {
  
        // Initialize all elements of temp as 0
        temp = Array(n).fill(0);
  
        // Set the right column for the left column
        // set by outer loop
        for (right = left; right < n; right++) {
  
            // Calculate sum between current left  
            // and right for every row 'i'
            for (i = 0; i < n; ++i)
                temp[i] += mat[i][right];
  
            // Count number of subarrays in temp[]
            // having sum divisible by 'k' and then 
            // add it to 'tot_count'
            tot_count += subCount(temp, n, k);
        }
    }
  
    // required count of sub-matrices having sum
    // divisible by 'k'
    return tot_count;
}
  
// Driver program to test above
var mat = [[5, -1, 6 ],
                    [-2, 3, 8 ],
                    [7, 4, -9 ]];
var n = 3, k = 4;
document.write( "Count = "
      + countSubmatrix(mat, n, k));
  
// This code is contributed by rrrtnx.
</script>


Output

Count = 6

Time Complexity: O(n^3). 
Auxiliary Space: O(n).



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads