Open In App

Count sub-matrices having sum divisible 'k'

Last Updated : 08 Mar, 2024
Comments
Improve
Suggest changes
Like Article
Like
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).


Next Article
Article Tags :
Practice Tags :

Similar Reads