zoukankan      html  css  js  c++  java
  • 每日一题_小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
    ");
                }
                else if (c >= l && c <= r)
                {
                    printf("%d
    ", c);
                }
                else
                {
                    for (j = top - 1; j >= 0; j--)
                    {
                        if (arr[j] >= l && arr[j] <= r)
                        {
                            flag = 1;
                            printf("%d
    ", arr[j]);
                            break;
                        }
                    }
                    if (flag == 0)
                    {
                        printf("-1
    ");
                    }
                }
    
    
            }
        }
    
        return 0;
    }

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

  • 相关阅读:
    动态规划 ------最短路径问题
    回溯算法 ------回溯算法的设计思想和适用条件
    回溯算法 ------ 回溯算法的设计思想及适用条件
    回溯算法 ------回溯算法的几个例子
    纯css实现翻书效果
    从vue源码看props
    js循环中使用async/await踩过的坑
    js实现word转换为html
    从vue源码看Vue.set()和this.$set()
    微信、qq二次分享
  • 原文地址:https://www.cnblogs.com/virusdefender/p/3465187.html
Copyright © 2011-2022 走看看