Last Updated on June 17, 2022 by Ria Pathak
Concepts Used
Sorting
Difficulty Level
Hard, Mathematics
Problem Statement (Simplified):
For a given range p
and q
, find the highest common factor of two given numbers, i.e. a
and b
. If no such number exists, return -1.
Test Case
Input:
8 12
4
2 10
3 7
2 2
5 6
Output:
4
4
2
-1
Explanation:
For 8 and 12, common divisors are [1,2,4].
In the range [2,10] we have 4 which is the maximum divisor in range.
In the range [3,7] we have 4 which is the maximum divisor in range.
In the range [2,2] we have 2 which is the maximum divisor in range.
In the range [5,6], there lies no divisor so we print -1.
See original problem statement here
Solving Approach :
1) The Highest common factor of any both numbers will be
gcd(a,b)
and there exists no factor above this.
2) So, to calculate all the factors we check all number which dividea
andb
both from 1 togcd(a,b)
and save them in an array.
3) We sort the array containing all common factors so that all factors are organized and searching factors in the range are easier.
4) Highest common factor in the given range [p,q
] can be found by searching lower bound ofp
and upper bound ofq
. Where,
- Upper Bound: Upper bound of any number
K
returns the position of immediate next number which exists in the array and is just greater thanK
.- Lower Bound: Lower bound of any number
K
returns the position of immediate previous number which exists in the array and is just smaller thanK
.
5) If the lower bound ofp
and upper bound ofq
is the same that means, there is no common factor in the range [p,q
].
6) If they are not same, the Highest Common factor in range will be the previous element to element at upper bound ofq
, as an element at the upper bound is greater thanq
, and element previous to it will be smaller thanq
and will be a common factor. Hence it is our answer, so we return the element.
Example
Let given numbers be
a=8
andb=12
We find
gcd(a,b)
as no factor lies beyondgcd(a,b)
which divided both numbers, hence,
gcd(a,b)
=4
We check all numbers between 1 and
gcd(a,b)
which divides both of our numbersa
andb
, we save such numbers in a array,We also sort this array so that factors are arranged in increasing order,
For given query
p
andq
, we checklower
bound
ofp
andupper
bound
ofq
, let’s assume two queries
- Query-1:
p=5
andq=6
Here,
lowerBound(p) = 4
andupperBound(q)=4
, as both values are same that means our query is beyond the range of factors, hence we return -1.
- Query-2:
p=2
andq=3
Here,
lowerBound(p) = 2
andupperBound(q)=4
, as both values are not same that means our range coincides with range of factors, hence our answer lies at factor less than upperBound(q) i.e. 3.
Solutions
#include <stdio.h> int gcd(int a, int b){ while(a!=0 && b!=0){ if(b%a==0) return a; int temp = a; a = b%a; b = temp; } return a; } int lowerBound(int a[], int start, int end, int key){ if (start > end) return end; int mid = (start + end) / 2; if (a[mid] == key) return mid; else if (a[mid] > key) return lowerBound(a, start, mid-1, key); else return lowerBound(a, mid+1, end, key); } int upperBound(int a[], int start, int end, int key){ if (start > end) return start; int mid = (start + end) / 2; if (a[mid] == key) return upperBound(a, mid+1, end, key); else if (a[mid] > key) return upperBound(a, start, mid-1, key); else return upperBound(a, mid+1, end, key); } int main() { int a,b; scanf("%d%d",&a,&b); int g = (a<b)?gcd(a,b):gcd(b,a); int divisors[9999999]={0}, count=0; for(int i=1; i<=g; i++) if(g%i==0) divisors[count++] = i; int n; scanf("%d",&n); while(n--){ int low,high; scanf("%d%d",&low,&high); int id1 = lowerBound(divisors,0,count-1, low); int id2 = upperBound(divisors,0,count-1, high); if(low>divisors[id1] || count==0) id1++; int diff = id2 - id1; if(diff == 0) printf("-1\n"); else printf("%d\n", divisors[id2-1]); } }
#include <bits/stdc++.h> using namespace std; int gcd(int a, int b){ while(a!=0 && b!=0){ if(b%a==0) return a; int temp = a; a = b%a; b = temp; } return a; } int lowerBound(int a[], int start, int end, int key){ if (start > end) return end; int mid = (start + end) / 2; if (a[mid] == key) return mid; else if (a[mid] > key) return lowerBound(a, start, mid-1, key); else return lowerBound(a, mid+1, end, key); } int upperBound(int a[], int start, int end, int key){ if (start > end) return start; int mid = (start + end) / 2; if (a[mid] == key) return upperBound(a, mid+1, end, key); else if (a[mid] > key) return upperBound(a, start, mid-1, key); else return upperBound(a, mid+1, end, key); } int main() { int a,b; cin>>a>>b; int g = (a<b)?gcd(a,b):gcd(b,a); int divisors[9999999]={0}, count=0; for(int i=1; i<=g; i++) if(g%i==0) divisors[count++] = i; int n; cin>>n; while(n--){ int low,high; cin>>low>>high; int id1 = lowerBound(divisors,0,count-1, low); int id2 = upperBound(divisors,0,count-1, high); if(low>divisors[id1] || count==0) id1++; int diff = id2 - id1; if(diff == 0) cout<<"-1\n"; else cout<<divisors[id2-1]<<endl; } }
import java.util.*; import java.io.*; public class Main { static int gcd(int a, int b){ while(a!=0 && b!=0){ if(b%a==0) return a; int temp = a; a = b%a; b = temp; } return a; } static int lowerBound(int a[], int start, int end, int key){ if (start > end) return end; int mid = (start + end) / 2; if (a[mid] == key) return mid; else if (a[mid] > key) return lowerBound(a, start, mid-1, key); else return lowerBound(a, mid+1, end, key); } static int upperBound(int a[], int start, int end, int key){ if (start > end) return start; int mid = (start + end) / 2; if (a[mid] == key) return upperBound(a, mid+1, end, key); else if (a[mid] > key) return upperBound(a, start, mid-1, key); else return upperBound(a, mid+1, end, key); } public static void main(String args[]) throws IOException { Scanner sc = new Scanner(System.in); int a = sc.nextInt(),b = sc.nextInt(); int g = (a<b)?gcd(a,b):gcd(b,a); int divisors[] = new int[9999999], count=0; for(int i=1; i<=g; i++) if(g%i==0) divisors[count++] = i; int n = sc.nextInt(); while(n--!=0){ int low = sc.nextInt(),high = sc.nextInt(); int id1 = lowerBound(divisors,0,count-1, low); int id2 = upperBound(divisors,0,count-1, high); if(count==0 || low>divisors[id1]) id1++; int diff = id2 - id1; if(diff == 0) System.out.println("-1"); else System.out.println(divisors[id2-1]); } } }
[forminator_quiz id="1237"]
Space Complexity is O(
min(A,B)
) to save all common factors.
This article tried to discuss the concept of Sorting. Hope this blog helps you understand the implementation. To practice more problems you can check out MYCODE | Competitive Programming.