给定两个正整数 a a a 和 b b b。
你需要回答 q q q 个询问。
每个询问给定两个整数
l
,
r
l,r
l,r,你需要找到最大的整数
x
x
x,满足:
x
x
x 是
a
a
a 和
b
b
b 的公约数。
l
≤
x
≤
r
l≤x≤r
l≤x≤r。
输入格式
第一行包含两个整数
a
,
b
a,b
a,b。
第二行包含一个整数 q q q。
接下来 q q q 行,每行包含两个整数 l , r l,r l,r。
输出格式
每个询问输出一行答案,即满足条件的最大的
x
x
x,如果询问无解,则输出 −1
。
数据范围
前六个测试点满足
1
≤
a
,
b
≤
100
,
1
≤
q
≤
20
1≤a,b≤100,1≤q≤20
1≤a,b≤100,1≤q≤20。
所有测试点满足
1
≤
a
,
b
≤
1
0
9
,
1
≤
q
≤
1
0
4
,
1
≤
l
≤
r
≤
1
0
9
1≤a,b≤10^9,1≤q≤10^4,1≤l≤r≤10^9
1≤a,b≤109,1≤q≤104,1≤l≤r≤109。
输入样例:
9 27
3
1 5
10 11
9 11
输出样例:
3
-1
9
注意这里我们需要找到特定的满足在范围内的最大约数,那么就不可以直接枚举所有范围内的数然后询问是否为约数,这样一定会超时。
注意这里有一个结论:两个数的公约数一定小于等于它的最大公约数,且这个公约数一定可以整除最大公约数。
所以预处理出来所有的公约数之后将其排序为有序序列,那么我们就可以二分出来一个答案。
首先围绕R来二分,如果一个数大于等于R就让其变小,除此之外使其变大。
如果到最后这个数是大于等于L的,就说明有解,否则无解。
#include<algorithm>
#include<iostream>
#include<vector>
using namespace std;
vector<int> get_divisors(int n){ //试除法求约数
vector<int>res; //此时求的是两数最大公约数的约数
for(int i = 1;i <= n/i;i++){
if(n % i == 0){
res.push_back(i);
if(i != n/i)res.push_back(n/i);
}
}
sort(res.begin(),res.end());
return res;
}
int gcd(int a,int b){
int c;
while(b){
c = a % b;
a = b;
b = c;
}
return a;
}
int main(){
int a,b;
cin >> a >> b;
int q;cin >> q;
vector<int>res = get_divisors(gcd(a,b));
while(q--){
int L,R;cin >> L >> R;
int l = 0,r = res.size() - 1;
while(l < r){
int mid = l + r + 1 >> 1;
if(res[mid] <= R)l = mid;
else r = mid - 1;
}
if(res[l] >= L)cout << res[l] << endl;
else cout << -1 << endl;
}
return 0;
}