CCF-GESP五级考级——初等数论,全网最精简的求最大公约数gcd和最小公倍数lcm方法(100%好使)

👑一、约数和因数的区别

        约数必须在整除的前提下才存在,而因数是从乘积的角度来提出的。如果数a与数b相乘的积是数ca\times bc的因数。
        1.约数只能对在整数范围内而言,而因数就不限于整数的范围。

举个栗子:2\times 8= 16。2和8是16的因数,也可以是16的约数。
另外一个栗子:0.9\times 8= 7.2,虽然可以说0.9X8是7.2的因数,却不能说0.9和8是7.2的约数。


        2.对于一个整数,凡能整除它的数,都是这个整数的约数。而因数只有在多个数字相乘等于n的时候,才能说

举个栗子:1、2、4、8、16都能整除16,因此,1、2、4、8、16也都是16的约数。

而当一个数被分解成两个或几个数相乘时,因数的个数就受到了限定。
另外一个栗子:2\times 6= 8。只能说2和8是16的因数,而不能说1、2、4、8、16都是16的因数,因为1\times 2\times 4\times 8\times 16的结果,并不等于16。

👑二、求最大公约数(gcd)

        最大公约数(Greatest Common Divisor)指两个或多个整数共有约数中最大的一个,一般称之为"gcd",是其英文单词小写的首字母缩写。

        a, b的最大公约数记为gcd(a, b), 其中需要满足{a\geqslant b\geqslant 0}的条件。

a=16 b=12
↓
分解a的约数集合:{1, 2, 4, 8, 16};
↓
分解b的约数集合:{1, 2, 3, 4, 6, 12};
↓
找到最大的公共约数,也就是①都存在于a和b约数集合中的②最大数字。
↓
最大公约数->4

        求最大公约数有多种方法,常见的有 质因数分解法、 短除法、 辗转相除法、 更相减损法。短除法如下图所示,它常常用于手算,面对程序题常见的大数无能为力,所以不过多介绍。

       “质因数分解法”和“更相减损法”速度较慢,且本文旨在精简,所以代码写一套最优秀的坤坤便可以了。所以咱们着重讲解“辗转相除法”,也就是广为人知的“欧几里得算法”。

欧几里得算法的演化🎈

        用gcd(a,b)表示a和b的最大公因数:有结论gcd(a,b)=gcd(a,ka+b)。

要证明这个原理很容易:如果p是a和ka+b的公约数,p整除a,也能整除ka+b.那么就必定要整除b,所以p又是a和b的公约数,从而证明他们的最大公约数也是相等的。推理如下

if gcd(a, ka+b) = p
↓
由于p是a的约数,那么 a % p == 0 , ka+b % p == 0
↓
当且仅当 ka % p == 0 并且 b % p == 0 的时候 (ka + b) % p 才成立
↓
所以{ka + b % p == 0}、{ka % p == 0 }、{b % p == 0} 

        基于上面的原理,就能实现我们的迭代相减法:

gcd(36,14)=gcd(2*14 + 8,14)=gcd(8, 14)=gcd(8, 8+6)=gcd(8, 6)=gcd(6+2, 6)=gcd(2, 6)=gcd(2, 3X2+0) = gcd(2, 0)

,而gcd(2,0)的最大公约数是2。

        0是所有整数的约数,因此 0 和任何整数的最大公约数都是这个整数本身。

 写代码🎈 

        那么如何使用C++代码实现欧几里得算法呢?

//input
a(int), b(int)

//algorithm
//和推理不一样的是,我们需要一直保持 a > b, 为了方便,取余的操作固定是a%b,所以需要保持a>b
if b < a:
    temp = b
    b = a 
    a = temp

//我们可以看到当b为0的时候我们才结束了推理,所以b=0是循环的终止条件
while b:
    //现在a > b了 先得到余数
    c = a % b 
    //让a = b, b = 余数,完美的交换的同时保持 a>b
    a = b 
    b = c      

//ouput
//最后b=0 a=最大公约数
gcd(a,b)->a

请同学们自行实现一下,之后可以对照一下下面的参考代码。

#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
    int T;
    cin >> T;
    while(T--)
    {
        int a, b;
        cin >> a >> b;
        //a % b == 0, 则b就是最大公约数,可以提前结束循环。
        while(a % b)
        {
            int c = a % b;
            a = b;
            b = c;
        }
        cout << b << endl;
    }
}

         大家学到这里一定非常幸苦,如果每次遇到gcd的题目,大家都要写这么多代码肯定很麻烦,接下来我们学习递归的方法。

#include<iostream>
#include<algorithm>
using namespace std;
int gcd(int a, int b){  // 一般要求a>=0, b>0。若a=b=0,代码也正确,返回0
	return b? gcd(b, a%b):a;
}
int main(){
    int a , b;
    cin >> a >> b;
    cout<<gcd(a,b)<<endl;
    return 0;
}

         哇,核心代码居然一共才写了三行

① int gcd(int a, int b){  // 一般要求a>=0, b>0。若a=b=0,代码也正确,返回0
②	return b? gcd(b, a%b):a;
}
③ cout<<gcd(a,b)<<endl;

那么如何理解呢,这是一个三目运算符,如果b≠0,就返回gcd(b, a%b),如果b=0,就返回a。

举个例子:
gcd(16, 12),进入下一层递归->gcd(12, 4),进入下一层递归 -> gcd(4, 0),返回上一层递归a=4->gcd(12,4),返回a=4->gcd(16, 12),返回a=4。所以最终结果就是4。是不是很神奇很奇妙呢?

            大家学到这里幸苦啦,但其实大家都白学了,这是因为👇

 白学了🎈

#include<iostream>
#include<algorithm> //这个头文件内置了一个求最大公约数的函数__gcd(a,b)
using namespace std;
int main(){
    int a, b;
    cin>> a >> b;
    cout<<__gcd(a,b)<<endl; //直接调用就写完了,核心代码就这一行,一行更比三行短。
    return 0;
}

👑三、求最小公倍数

        记公式

        然后就做完了 

#include<iostream>
#include<algorithm>
using namespace std;
int main(){
    int a,b;
    cin>>a>>b;
    cout<<a*b/__gcd(a,b)<<endl;
    return 0;
}
  • 20
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
辗转相除法是一种求最大公因数的常用方法。在C++中,可以使用以下代码实现辗转相除法求最大公因数: ```cpp #include <iostream> using namespace std; int gcd(int a, int b) { if (b == 0) return a; else return gcd(b, a % b); } int main() { int m, n; cin >> m >> n; cout << gcd(m, n); return 0; } ``` 以上代码中,`gcd`函数使用递归的方式实现了辗转相除法。在`main`函数中,首先读入两个整数m和n,然后调用`gcd`函数求它们的最大公因数,并输出结果。 你可以将需要求最大公因数的两个数作为输入,然后运行这段代码,即可得到它们的最大公因数。 #### 引用[.reference_title] - *1* *2* [C++辗转相除求两个数的最大公因数(即最大公约数)](https://blog.csdn.net/weixin_46846304/article/details/116541722)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [C++ 辗转相除法求最大公约数 最小公倍数](https://blog.csdn.net/weixin_61657293/article/details/123057552)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大气层煮月亮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值