给定两个正整数 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;
}