Count sub-matrices having sum divisible 'k' - GeeksforGeeks

20 May, 2021
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. 
C++
Java
Python3
C#
PHP
Javascript
// 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 kint 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 aboveint 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 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 kstatic 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 codepublic 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.
# Python implementation to# count sub-matrices having# sum divisible by the# value 'k' # function to count all# sub-arrays divisible by kdef 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 Codemat = [[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# 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 implementation to// count sub-matrices having// sum divisible by the// value 'k' // function to count all// sub-arrays divisible by kfunction 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)?>
<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 kfunction 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 abovevar 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). 
manishshaw1
rrrtnx
divisibility
Matrix
Matrix
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Comments
Old Comments
Sudoku | Backtracking-7
Divide and Conquer | Set 5 (Strassen's Matrix Multiplication)
Program to multiply two matrices
Inplace rotate square matrix by 90 degrees | Set 1
Count all possible paths from top left to bottom right of a mXn matrix
Min Cost Path | DP-6
The Celebrity Problem
Printing all solutions in N-Queen Problem
Rotate a matrix by 90 degree in clockwise direction without using any extra space
Python program to multiply two matrices