题目描述
Well, here is another math class task. In mathematics, GCD is the greatest common divisor, and it's an easy task to calculate the GCD between two positive integers.
A common divisor for two positive numbers is a number which both numbers are divisible by.
But your teacher wants to give you a harder task, in this task you have to find the greatest common divisor dd between two integers aa and bb that is in a given range from lowlow to highhig**h (inclusive), i.e. low<=d<=highlow<=d<=hig**h . It is possible that there is no common divisor in the given range.
You will be given the two integers aa and bb , then nn queries. Each query is a range from lowlow to highhig**h and you have to answer each query.
输入格式
The first line contains two integers aa and bb , the two integers as described above ( 1<=a,b<=10^{9}1<=a,b<=109 ). The second line contains one integer nn , the number of queries ( 1<=n<=10^{4}1<=n<=104 ). Then nn lines follow, each line contains one query consisting of two integers, lowlow and highhig**h ( 1<=low<=high<=10^{9}1<=low<=hig**h<=109 ).
输出格式
Print nn lines. The ii -th of them should contain the result of the ii -th query in the input. If there is no common divisor in the given range for any query, you should print -1 as a result for this query.
题意翻译
题目大意:
找出a,b的最大公因子,然后给几个查询,每次查询包含x,y两个数字,查询在x~y之间的a,b的最大公因子
Translated by @Harryheqg
题解:
关键性质:
两个数的任意公因子一定是其最大公因子的因子。
这个性质的正确性是显然的。
如果数感不太好,完全可以用反证法证明一下。
然后就自然而然地想到先求gcd,再处理gcd的所有约数,再在其上二分查找。
二分查找的形式多种多样,可以手动,也可以STL upper_bound,你要是喜欢,打一棵权值线段树也没人管你。
我用的是upper_bound:
代码:
#include<cstdio>
#include<cmath>
#include<vector>
#include<algorithm>
using namespace std;
int a,b;
vector<int> v;
int gcd(int a,int b)
{
return !b?a:gcd(b,a%b);
}
void fac(int x)
{
for(int i=1;i<=sqrt(x);i++)
if(x%i==0)
{
v.push_back(i),v.push_back(x/i);
if(i==x/i)
v.pop_back();
}
}
int main()
{
scanf("%d%d",&a,&b);
int g=gcd(a,b);
fac(g);
sort(v.begin(),v.end());
int t;
scanf("%d",&t);
while(t--)
{
int x,y;
scanf("%d%d",&x,&y);
int pos=upper_bound(v.begin(),v.end(),y)-v.begin();
pos--;
if(v[pos]<x)
puts("-1");
else
printf("%d\n",v[pos]);
}
return 0;
}