zoukankan      html  css  js  c++  java
  • 最大公约数与最小公倍数

    基础知识

    最大公约数:

    最大公约数就是两个数的最大公共因子

    x = abc , y = bcdef  (a ~ f 均为质因子)

    gcd ( x , y ) = bc

    计算方法:

    1.质因数分解法,如上举例所示

    2.欧几里得算法(辗转相除法)

    算法原理:gcd(a,b) = gcd( b ,  a % b)  

    三目运算符(较快)

    int gcd(int a , int b ){
        return !b ? a : gcd(b, a % b);
    }

    位运算(超快)( a , b不能为0)

    int gcd(int a , int b){
        while(b ^= a ^= b ^= a %= b);
        return a;
    }

     分析:

    b^=a^=b^=a%=b可以写为  a%=b ,  b ^= a , a ^= b , b ^= a ; 

    后面三句相当于swap(a , b)

    于是就变为a %= b , swap(a , b)

    这就是最基本的辗转相除法

    https://blog.csdn.net/Ljnoit/article/details/104604806

    最小公倍数

    最小公倍数是两个数的所有质因子的积

    x = abc , y = bcdef  (均为质因子)

    则  lcm(x , y ) = abcdef

    (分式加减时都要将分母化为最小公倍数)

    计算方法:

    lcm( a , b ) = a * b / gcd( a , b )

    常用性质

    • gcd(b∗ lcm(a,ba * b
    • gcd(a , b) = m , 则 gcd( a/m , b/m ) = 1
    • 同理,若lcm( a , b ) = k , 则 gcd( k/b , k/a ) = 1

    例题

    1.最大公约数与最小公倍数问题

    (https://www.luogu.com.cn/problem/P1029)

    解题思路:

    gcd(P,Q)  = x0, lcm(P,Q) = y0   可推出  x0 <= P , Q <= y0 

    确定了范围,然后 双层遍历,看是否满足条件就好  这样会超时,所以要将算法优化到O(N)

    将Q用P表示就好,利用性质   gcd(P , Q∗ lcm(P , Q= P * Q

    Q = x0 * y0 / P;

    注意:

    遍历从x0 ~ sqrt(x0*y0)  是因为结果 P * Q  和 结果 Q * P ,只用算一次,之后再乘2就好,但是如果x0 == y0 ,只用 加1次

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    int gcd(int a , int b){
        return !b ? a : gcd(b, a%b);
    }
    int main(){
        int x0,y0;
        cin >> x0 >> y0;
        int t = x0 * y0;
        int ans = 0;
        for(int i = x0 ; i < (int)sqrt(t) ; i++){
            if(t % i == 0 && gcd(t/i , i) == x0){
                ans++;
            }
        }
        if(t % (int)sqrt(t) == 0 && gcd(t / (int)sqrt(t),(int)sqrt(t)) == x0)
            cout << ans*2 + 1 << endl; 
        else 
            cout << ans*2 << endl;
        return 0;
    }

    2.P1072 Hankson 的趣味题

    https://www.luogu.com.cn/problem/P1072

    比较好的题解:https://www.luogu.com.cn/blog/zzlzk/solution-p1072

    题意:

    输入四个数,a0,a1,b0,b1 求x使得条件:

    1. x 和 a0 的最大公约数是 a1

    2. x 和 b0 的最小公倍数是 b1

    问x的个数

    解题思路: 

    由题意能得到的信息

    • x一定时最小公倍数 b1 的因子,一定是最大公约数 a1 的倍数,a1 <= x <= b1

    我们要做的就是从1到sqrt(b1)遍历其因子,且该因子能 整除 a1,

    同时它还要满足题中的两个条件,如果都满足 ans++

    注意:相等因子只加一次

    *** 这里有个问题,如果按照题中条件判断有可能爆int导致判断不准,所以我们要对条件进行处理

    用到了性质

    • 若gcd(a , b) = m , 则 gcd( a/m , b/m ) = 1
    • 同理,若lcm( a , b ) = k , 则 gcd( k/b , k/a ) = 1
    #include<bits/stdc++.h>
    using namespace std;
    int gcd(int a,int b){
        if(b > a)swap(a,b);
        return !b ? a : gcd(b , a % b);
    }
    int main(){
        int t;
        scanf("%d",&t);
        while(t--){
            int a0,a1,b0,b1;
            scanf("%d %d %d %d",&a0,&a1,&b0,&b1);
            int ans = 0;
            for(int i = 1 ; i * i <= b1; i++){
                if(b1 % i != 0)continue;//不是因子,继续 
                if((i % a1 == 0) && gcd( i , a0 ) == a1 && gcd( b1/b0 , b1/i ) == 1){
                    ans++;
                }
                int j = b1 / i;
                if(j == i)continue;//相等因子只判断一次 
                if((j % a1 == 0) && gcd( j , a0 ) == a1 && gcd( b1/b0 , b1/j ) == 1){
                    ans++;
                }
            }
            printf("%d
    ",ans);
        }
        return 0;
    }

    如果还是不理解可以看上面大佬的博客

    3.P4057 [Code+#1]晨跑

    https://www.luogu.com.cn/problem/P4057

    这个题比较简单,就是给出三个人每隔几天运动 的天数a,b,c,问三个人下次碰到是什么时候

    就是三人的最小公倍数

    #include<bits/stdc++.h>
    using namespace std;
    long long gcd(long long a , long long b){
        if(!b)return a;
        else return gcd(b,a%b);
    }
    int main(){
        long long a,b,c;
        scanf("%lld %lld %lld",&a,&b,&c);
        long long ans = a / gcd(a,b) * b;
        ans = ans / gcd(ans,c) * c;
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    又过了一周
    本周学习情况
    5.12
    一周回顾
    npm修改全局包安装路径
    热力图之heatmap
    前端的发展历程
    idea打开maven项目没有别识别是maven项目
    nginx下部署vue项目
    WEB前端开发NodeJS
  • 原文地址:https://www.cnblogs.com/w-w-t/p/13173019.html
Copyright © 2011-2022 走看看