【题解】约数

题目描述

        给出两个正整数X和Y,求X和Y的最大公约数,奶牛可以轻松解决这个问题。

        农夫Farmer John决定改一改题目去考验奶牛。农夫决定询问奶牛Q个问题,每个问题的格式是这样的:

        农夫给定两个正整数a和b,农夫保证a≤b,然后农夫询问奶牛:在a至b的范围内,有没有哪个整数既是X的约数同时又是Y的约数?如果有,输出最大的那个;如果没有,输出-1。

输入输出格式

输入格式

        第一行,两个正整数,X和Y。

        第二行,一个整数数,Q。

        接下来有Q行,每行两个正整数:a和b,其中保证a≤b。

输出格式

        共Q行,每行一个整数,每行对应农夫的一个问题。

输入输出样例

输入样例一

200 120

3

9 40

25 35

10 15

输出样例一

40

-1

10

输入样例二

10 10
2
1 6
5 5
 

输出样例二

5

5

说明

数据规模

        对于40%的数据:1≤X≤100,1≤Y≤100,1≤Q≤100,1≤a<b≤100;

        对于100%的数据:1≤X≤1000000000,1≤Y≤1000000000,1≤Q≤30000,1≤a<b≤1000000000。

题解

        我们可以以根号n的时间复杂度来枚举出n的约数,然后暴力求公约数,再用二分来回应询问即可。

#include <iostream>
#include <cstdio>
#include <cmath>

using namespace std;

int x, y;
int q;
int ax[700000], cntx;
int ay[700000], cnty;
int a[1400000], cnt;

void Init(int obj, int srobj, int a[], int & cnt)
{
    for(register int i = 1; i <= srobj; ++i)
    {
        if(obj % i) continue;
        a[++cnt] = i;
    }
    for(register int i = cnt; i; --i)
    {
        a[++cnt] = obj / a[i];
    }
    return;
}

void Work()
{
    int i = 1, j = 1;
    while(i <= cntx && j <= cnty)
    {
        if(ax[i] == ay[j])
        { 
            a[++cnt] = ax[i];
            ++i;
            ++j;
        }
        else if(ax[i] < ay[j]) ++i;
        else ++j;
    }
    return;
}

int Solve(int minn, int maxn)
{
    int ans = -1;
    int lt = 1, rt = cnt, mid;
    while(lt <= rt)
    {
        mid = lt + rt >> 1;
        if(a[mid] <= maxn) ans = a[mid], lt = mid + 1;
        else rt = mid - 1;
    }
    if(ans >= minn) return ans;
    return -1;
}

int main()
{
    scanf("%d%d%d", &x, &y, &q);
    Init(x, sqrt(x), ax, cntx);
    Init(y, sqrt(y), ay, cnty);
    Work();
    ++q;
    int minn, maxn;
    while(--q)
    {
        scanf("%d%d", &minn, &maxn);
        printf("%d\n", Solve(minn, maxn));
    }
    return 0;
}
参考程序

猜你喜欢

转载自www.cnblogs.com/kcn999/p/10356726.html