Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Count subarrays divisible by K

Tags:

c++

algorithm

Given a sequence of n positive integers we need to count consecutive sub-sequences whose sum is divisible by k.

Constraints : N is up to 10^6 and each element up to 10^9 and K is up to 100

EXAMPLE : Let N=5 and K=3 and array be 1 2 3 4 1

Here answer is 4

Explanation : there exists, 4 sub-sequences whose sum is divisible by 3, they are

3
1 2
1 2 3
2 3 4

My Attempt :

long long int count=0;
for(int i=0;i<n;i++){
    long long int sum=0;
    for(int j=i;j<n;j++)
    {
        sum=sum+arr[j];
        if(sum%k==0)
        {
            count++;
        }
    }
}

But obviously its poor approach. Can their be better approach for this question? Please help.

Complete Question: https://www.hackerrank.com/contests/w6/challenges/consecutive-subsequences

like image 941
user3786422 Avatar asked Jul 01 '14 20:07

user3786422


People also ask

How do you find the number of Subarrays whose Max K is?

// Stores count of subarrays with max <= k - 1. int count1 = totalSubarrays(arr, n, k - 1); // Stores count of subarrays with max >= k + 1. int count2 = totalSubarrays(arr, n, k);

How do you find the number of Subarrays?

The total number of subarrays in an array of size N is N * (N + 1) / 2. The count of subarrays with an odd product is equal to the total number of continuous odd elements present in the array. Therefore, count of subarrays with even product = (Total number of subarrays – Subarrays with the odd product).

How do you count Subarrays in an array?

We can easily calculate the number of sub-arrays of an array which has all 1s by using the formula n*(n+1)/2, where n is the length of the array with all 1s. Calculate the length of every sub-array which has all 1s and increment the count variable by length*(length+1)/2.


1 Answers

Here is a fast O(n + k) solution:

1)Lets compute prefix sums pref[i](for 0 <= i < n).

2)Now we can compute count[i] - the number of prefixes with sum i modulo k(0 <= i < k). This can be done by iterating over all the prefixes and making count[pref[i] % k]++. Initially, count[0] = 1(an empty prefix has sum 0) and 0 for i != 0.

3)The answer is sum count[i] * (count[i] - 1) / 2 for all i.

4)It is better to compute prefix sums modulo k to avoid overflow.

Why does it work? Let's take a closer a look at a subarray divisible by k. Let's say that it starts in L position and ends in R position. It is divisible by k if and only if pref[L - 1] == pref[R] (modulo k) because their differnce is zero modulo k(by definition of divisibility). So for each fixed modulo, we can pick any two prefixes with this prefix sum modulo k(and there are exactly count[i] * (count[i] - 1) / 2 ways to do it).

Here is my code:

long long get_count(const vector<int>& vec, int k) {
  //Initialize count array.
  vector<int> cnt_mod(k, 0);
  cnt_mod[0] = 1;
  int pref_sum = 0;
  //Iterate over the input sequence.
  for (int elem : vec) {
    pref_sum += elem;
    pref_sum %= k;
    cnt_mod[pref_sum]++;
  }
  //Compute the answer.
  long long res = 0;
  for (int mod = 0; mod < k; mod++)
    res += (long long)cnt_mod[mod] * (cnt_mod[mod] - 1) / 2;
  return res;
}
like image 114
kraskevich Avatar answered Oct 09 '22 09:10

kraskevich