每日一题_小M的区间公约数_数论

小M的区间公约数

Time Limit:1 Ms| Memory Limit:10 MB
Difficulty:0

[Problem] [Rank]

Description
小M对最大公约数已经很熟悉了,今天突发奇想,她想知道区间最大的公约数。两个数a,b,然后有n组询问,每组询问[L,R],输出[L,R]区间中a,b最大的公约数,没有输出-1。
Input
第一行输入a,b, (1 ≤ a, b ≤ 10^9)
第二行输入n,(1 ≤ n ≤ 10^4)
然后接下来n行,每行[L,R]。(1 ≤ L ≤ R ≤ 10^9)
Output
输出每次询问的结果。
Sample Input
9 27
3 
1 5
10 11
9 11
Sample Output
3
-1
9

这个题目如果是在不考虑极限情况的时候,是挺简单的,就是先计算这两个数的真正的最大公约数,然后这个和区间的相对情况进行比较。

当最大公约数大于这个区间的时候,就用到了穷举,从区间的右端点开始直到左端点,当然这个应该是比较浪费时间的。

如果不是这样做的话,就是应该把这两个数的所有的约数都计算出来(计算约数只要算到根号下这个数就行了),然后进行处理,找到共同的,也就是这两个数的约数,

然后和这个区间进行比对。

但是这样的话,还是有些麻烦,后来发现,两个数的最大公约数的约数就是这两个数的约数,这样计算最大公约数的约数就好了,还不用去比较和去重了。

代码:

 

 

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int gcd(int a, int b)
{
    if (b == 0)
    {
        return a;
    }
    else
    {
        return gcd(b, a % b);
    }
}

int cmp_1(const void *a, const void *b)
{
    return *(int *) a - *(int *) b;
}

int arr[10000];

int main()
{
    int a, b;
    int n;
    int l, r;
    int i, j;
    int c;
    int top;
    int flag;
    while (scanf("%d%d", &a, &b) != EOF)
    {
        top = 0;
        
        memset(arr, -1, sizeof(arr));
        //计算a和b的最大公约数
        if (a >= b)
        {
            c = gcd(a, b);
        }
        else
        {
            c = gcd(b, a);
        }
        //求最大公约数的约数
        for (j = 1; j * j <= c; j++)
        {
            if (c % j == 0)
            {
                arr[top++] = j;
                arr[top++] = c / j;
            }
        }
        //然后排序
        qsort(arr, top, sizeof(int), cmp_1);
        scanf("%d", &n);
        while (n--)
        {
            flag = 1;
            scanf("%d%d", &l, &r);
            if (c < l)
            {
                printf("-1\n");
            }
            else if (c >= l && c <= r)
            {
                printf("%d\n", c);
            }
            else
            {
                for (j = top - 1; j >= 0; j--)
                {
                    if (arr[j] >= l && arr[j] <= r)
                    {
                        flag = 1;
                        printf("%d\n", arr[j]);
                        break;
                    }
                }
                if (flag == 0)
                {
                    printf("-1\n");
                }
            }


        }
    }

    return 0;
}

这个题目还要注意的就是有的计算可能很多组数据只需要计算一次,别放错地方,浪费时间。比如这个题的计算最大公约数的约数,不用放在while(n--)中,在外面就可以的。

 

 

posted @ 2013-12-09 13:03  virusdefender  阅读(443)  评论(0编辑  收藏  举报