nyoj 881 小M的区间公约数

点击打开连接php


首先给的范围很大,是10^9。暴力解确定超时(单用for循环到10^9都大约要2s-3s),首先写了个程序暴力的把两个数全部的约数都打印出来,最后发现全部的公约数都是最大公约数的约数,而且最大公约数的约数也必定是两个数的公约数,由此题目转换为求最大公约数的约数的问题,觉得输入最大是10^9,因此公约数最大是5*10^8,求这个数的全部约数只须要循环到(跟号5)*10^4,for循环能够轻松应对了,直接用for获得全部的约数,而后qsort排序后,把数组的结构抽象成数轴上的n多个点,每一个点都是这两个数的约数了,剩下的工做就是从大到小循环全部的公约数找第一个在查询区间里的约数就是要求的解。数组

附上AC代码:.net

#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(const void *a, const void *b)
{
    return *(int *)b - *(int *)a;
}
int array[10000];
int top;
int main()
{
    int a, b;
    while(scanf("%d %d", &a, &b) != EOF)
    {
        memset(array, 0, sizeof(array));
        top = 0;
        int n;
        if(a < b)
        {
            int swap = a;
            a = b;
            b = swap;
        }
        int max = gcd(a, b);
        int i;
        for(i = 1; i * i < max; i++)
        {
            if(max % i == 0)
            {
                array[top++] = i;
                array[top++] = max / i;
            }
        }
        if(i * i == max)
            array[top ++] = i;
        qsort(array, top, sizeof(int), cmp); 
        scanf("%d", &n);
        while(n--)
        {
            int l, r;
            scanf("%d %d", &l, &r);
            int k;
            if(l > max)
            {
                printf("-1\n");
                continue;
            }
            for(k = 0; k < top; k++)
            {
                if(l <= array[k] && r >= array[k])
                {
                    printf("%d\n", array[k]);
                    break;
                }
                else if(l > array[k])
                {
                    printf("-1\n");
                    break;
                }
            }
        }
    }
    return 0;
}
相关文章
相关标签/搜索