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++
// 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) ?> |
Output:
Count = 6
Time Complexity: O(n^3).
Auxiliary Space: O(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.

