 COWF1 - Editorial

Author: Sandeep Singh
Tester: Arkapravo Ghosh
Editorialist: Sandeep Singh

EASY

GCD

PROBLEM:

You are given an array A of integers of size N . You will be given Q queries. In each query you are giveny two integers L & R . You have to find the gcd (Greatest Common Divisor) of the array after excluding the part from range L to R inclusive.

EXPLANATION:

(Please note that I have used 1 based indexing throughout the editorial)
The solutions to this problem makes use of the property of gcd according to which gcd(a,b,c)=gcd(gcd(a,b),c).

We observe that for each query represented by L and R, We have to calculate GCD of gcd(A_1, A_2,...,A_{L-1}) and gcd(A_{R+1},A_{R+2},...,A_N) . We can do so by precalculating a prefix and a suffix gcd subarray.

Let’s define the prefix and suffix array as follows:
prefix_i=gcd(A_1,A_2,....A_i)
suffix_i=gcd(A_N,A_{N-1},....A_i)

Keeping in mind the above-mentioned property of gcds, we observe that the answer to each query is simply gcd of prefix_{L-1} and suffix_{R+1}

The prefix and suffix arrays are also calculated by the use of the above-mentioned property of gcd.
Prefix_i = GCD( Prefix_{i-1} , A_{i} )
Suffix_i = GCD( Suffix_{i+1} , A_i )

Below is the code to build the prefix and suffix arrays in O(N) time complexity.

prefix=suffix[N+1]=0; //base case
for (i=1 ;i<=N; i++)
prefix[i] = GCD (prefix[i-1], arr[i]);

for (int i=N; i>=1 ;i--)
suffix[i] = GCD (suffix[i+1], arr[i]);

Time complexity is O((N+Q)*K) where K is for gcd calculation.

SOLUTIONS:

Setter's Solution
clude <bits/stdc++.h>
#define ll long long int
#define M 1000000007
using namespace std;
int GCD(int a, int b)
{
if (b==0)
return a;
return GCD (b, a%b);
}

void solve(){
int N,Q,i,L,R;
cin>>N>>Q;
int arr[N+2],prefix[N+2],suffix[N+2];

memset(arr,0,sizeof(arr));
memset(prefix,0,sizeof(prefix));
memset(suffix,0,sizeof(suffix));

for(i=1;i<=N;i++)
cin>>arr[i];

for (i=1 ;i<=N; i++)
prefix[i] = GCD (prefix[i-1], arr[i]);

for (int i=N; i>=1 ;i--)
suffix[i] = GCD (suffix[i+1], arr[i]);
while(Q--){
cin>>L>>R;
cout << GCD(prefix[L-1],suffix[R+1]) << endl;
}

}
int main() {
ios_base:: sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);

//freopen("ip6.in", "r", stdin);
//freopen("op6.out", "w", stdout);

int T ;
cin>>T;
while(T--)
solve();
return 0;
}

Tester's Solution
from math import *

for _ in range(int(input())):
n, q = map(int, input().split())
a =  + list(map(int, input().split()))
dpl = [0 for __ in range(n+2)]
dpr = [0 for __ in range(n+2)]
for i in range(1, n+1):
dpl[i] = gcd(dpl[i-1], a[i])
dpr[n-i+1] = gcd(dpr[n-i+2], a[n-i+1])
for __ in range(q):
l, r = map(int, input().split())
print(gcd(dpl[l-1], dpr[r+1]))
2 Likes

@sandeep1103 What if we need to calculate the GCD in the range [L to R] for each query, then how can we solve this question?

For such queries, you can use segment tree.

1 Like