Count subarrays whose product is divisible by k in C++


Given an array arr[] and an integer k as input. The goal is to find the number of subarrays of arr[] such that the product of elements of that subarray is divisible by k.

For Example

Input

arr[] = {2, 1, 5, 8} k=4

Output

Count of sub-arrays whose product is divisible by k are: 4

Explanation

The subarrays will be:
[ 8 ], [ 5,8 ], [ 1,5,8 ], [ 2,1,5,8 ].

Input

arr[] = {7,1,9,7} k=9

Output

Count of sub−arrays whose product is divisible by k are: 6

Explanation

The subarrays will be:
[ 9 ], [ 9,7 ], [ 1,9 ], [ 1,9,7 ], [ 7,1,9 ], [ 7,1,9,7 ].

Approach used in the below program is as follows

Naive Approach

We will solve this problem using two approaches. In the naive approach, simply traverse the array using two for loops and for each subarray between indexes i and j check if the product of elements is divisible by k. If yes then increment count.

  • Take an integer array arr[] and k as input.

  • Function product_k(int arr[], int size, int k) takes an array and k and returns a count of sub−arrays whose product is divisible by k.

  • Take the initial count as input.

  • Traverse arr from i=0 to i<size and j=i to j<size. And k=i to k<=j

  • For each subarray arr[ i to j ], multiply arr[k] to temp.

  • If product temp is divisible by k then increment count.

  • At the end of all three loops, return count as result.

Efficient Approach

WIn this approach instead of traversing each subarray, we will store the products in the segment tree. Now use products from this tree that are divisible by k. And increment count accordingly.

  • Take an integer array arr[] and k as input.

  • We will implement segment tree as an array arr_2[4 * size_2].

  • Function set_in(int fit, int first, int last, const int* arr, int k) is used to build the segment tree for products.

  • Function check(int fit, int first, int last, int start, int end, int k) is used to find the product of subarray between start and end.

  • If first>last or first>end or last<start return 1.

  • If first>=last and last<=end then return arr_2[fir]%k.

  • Set level=first+last >> 1 (divide by 2 ).

  • Now recursive call check() for level and level+1 and store in set_1 and set_2.

  • Set count=set_1+set_2 and return count.

  • Function product_k(int arr[], int size, int k) takes arr[] and k and returns the count of sub−arrays whose product is divisible by k.

  • Take the initial count as 0.

  • Set the initial count as 0.

  • Traverse using two for loops from i=0 to i<size and j=0 to j<size. Set temp=check(1, 0, size − 1, i, j, k).

  • If this temp is 0 then increment count.

  • Return count as final result.

Example

 Live Demo

#include <bits/stdc++.h>
using namespace std;
int product_k(int arr[], int size, int k){
   int count = 0;
   for (int i = 0; i < size; i++){
      for (int j = i; j < size; j++){
         int temp = 1;
         for (int k = i; k <= j; k++){
            temp = temp * arr[k];
         }
         if(temp % k == 0){
            count++;
         }
      }
   }
   return count;
}
int main(){
   int arr[] = {2, 1, 5, 8, 10, 12 };
   int size = sizeof(arr) / sizeof(arr[0]);
   int k = 2;
   cout<<"Count of sub−arrays whose product is divisible by k are: "<<product_k(arr, size, k);
   return 0;
}

Output

If we run the above code it will generate the following output −

Count of sub−arrays whose product is divisible by k are: 18

Example(Efficient Approach)

 Live Demo

#include <bits/stdc++.h>
using namespace std;
#define size_2 100002
int arr_2[4 * size_2];
void set_in(int fit, int first, int last, const int* arr, int k){
   if (first == last){
      arr_2[fit] = (1LL * arr[first]) % k;
      return;
   }
   int level = (first + last) >> 1;
   set_in(2 * fit, first, level, arr, k);
   set_in(2 * fit + 1, level + 1, last, arr, k);
   arr_2[fit] = (arr_2[2 * fit] * arr_2[2 * fit + 1]) % k;
}
int check(int fit, int first, int last, int start, int end, int k){
   if(first > last){
      return 1;
   }
   if(first > end){
      return 1;
   }
   if(last < start){
      return 1;
   }
   if (first >= start){
      if(last <= end){
         return arr_2[fit] % k;
      }
   }
   int level = (first + last) >> 1;
   int set_1 = check(2 * fit, first, level, start, end, k);
   int set_2 = check(2 * fit + 1, level + 1, last, start, end, k);
   int count = (set_1 * set_2) % k;
   return count;
}
int product_k(int arr[], int size, int k){
   int count = 0;
   for (int i = 0; i < size; i++){
      for (int j = i; j < size; j++){
         int temp = check(1, 0, size − 1, i, j, k);
         if (temp == 0){
            count++;
         }
      }
   }
   return count;
}
int main(){
   int arr[] = {2, 1, 5, 8, 10, 12};
   int size = sizeof(arr) / sizeof(arr[0]);
   int k = 2;
   set_in(1, 0, size − 1, arr, k);
   cout<<"Count of sub−arrays whose product is divisible by k are: "<<product_k(arr, size, k);
   return 0;
}

Output

If we run the above code it will generate the following output −

Count of sub−arrays whose product is divisible by k are: 18

Updated on: 05-Jan-2021

221 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements