sum of the GCD of all the subarrays

Aug 28, 2019 at 5:07pm
what is the most efficient way to find the sum of gcds of all the subarray without using tabular DP(as the memory constraints doesn't allow to form 2D array)
Aug 28, 2019 at 5:18pm
what does all subarray mean here? every combination?
Aug 28, 2019 at 7:44pm
Subarray means continuous subsequence
Aug 28, 2019 at 8:41pm
So just to be clear on the terminology, if the array as a whole is [2, 4, 6], you must skip gcd(2, 6)?

I'm sure websites like geeksforgeeks have had this question done dozens of times, so you could just search for it, it sounds like a code competition question.
Last edited on Aug 28, 2019 at 8:41pm
Aug 28, 2019 at 9:55pm
> memory constraints doesn't allow to form 2D array
if the idea is to create a matrix where G[j][k] = gcd(v[j]...v[k]) then you need to notice that it will have a lot of repeated elements
so you may compress that information and it will not exceed the memory limit
Last edited on Aug 28, 2019 at 9:56pm
Aug 28, 2019 at 10:01pm
gcd probably has properties that help. there is likely something like gcd (2,4) and gcd(2,4,6) that you can do to save work, to find the second one faster using knowledge of the first one.. these things are math problems first, coding second, go do the math.
Aug 29, 2019 at 1:00am
some properties
1
2
3
gcd(a,b,c) = gcd(gcd(a,b), c)
gcd(a, b) <= min(a,b)
gcd(a, 1) = 1
Aug 29, 2019 at 5:57am
@ne555 can you explain how to compress the dp array?
Aug 29, 2019 at 7:46am
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <iostream>
#include <vector>
using namespace std;

//================================================

int gcd( int a, int b )
{
   return b ? gcd( b, a % b ) : a;
}

//================================================

int sumAll( const vector<int> A )
{
   int N = A.size();
   vector<int> B = A;
   int sum = 0;

   for ( int i : B ) sum += i;                   // subsequences of length 1

   for ( int Lm1 = 1; Lm1 < N; Lm1++ )           // subsequences of length 2, ..., N
   {                                             //      Lm1 is length minus 1
      int sumlast = sum;
      for ( int i = 0; i + Lm1 < N; i++ )        // replace element B[i] with
      {                                          //      gcd( A[i], ..., A[i+Lm1] )
         if ( B[i] != 1 ) B[i] = gcd( B[i], A[i+Lm1] );
         sum += B[i];
      }

      if ( sum - sumlast == N - Lm1 )            // shortcut exit once all B[i] are 1
      {
         int triangle = N - Lm1 - 1;
         if ( triangle > 0 ) sum += triangle * ( triangle + 1 ) / 2;
         break;
      }
   }
   return sum;
}

//================================================

int main()
{
   vector<int> A = { 6, 18, 12, 36, 5 };
   cout << sumAll( A );
}
Aug 29, 2019 at 2:03pm
for example https://en.wikipedia.org/wiki/Run-length_encoding
also, because of symmetry, you may just work on the lower triangle

1
2
3
GCD[0] = {v[0], 1}
for K in range(1,n):
	GCD[K] = compress({gcd(GCD[K-1], v[K]), {v[K], 1}})
so we store pairs {value, count}
we'll fill the lower triangle, so at each step, compute the gcd between each element of the previous row and the current v_k
then in compress(), just check for contiguous elements that have the same value and sum their count.
Aug 29, 2019 at 7:29pm
@ne555
Can you write the code implementation of the above explanation for an example
Aug 29, 2019 at 10:43pm
1
2
3
4
5
6
7
8
def compress(array):
	result = {array[0]}
	for K in range(1, len(array)):
		if array[K].value == array[K-1].value: //same element, update the count
			result.back().count += array[K].count
		else: //new element, insert it
			result.append(array[K])
	return result
Aug 29, 2019 at 11:16pm
notacoder wrote:
Can you write the code implementation of the above explanation for an example

Can you do anything yourself?
Topic archived. No new replies allowed.