求两个数的最大公约数和最小公倍数
求两个数的最大公约数和最小公倍数#
一查发现竟然有这么多种方法,除了之前最常用的辗转相除的方法,还有不包括辗转相除的其他三种办法
辗转相除法又称欧几里得算法,据说是最早的算法,是西方的算法
东方的有《九章算术》中的更相减损术
还有将辗转相除法和更相减损术结合起来的运用了移位运算的方法
直接写代码了
辗转相除法的依据是一条定理:两个正整数a和b(a>b),它们的最大公约数等于a除以b的余数c和b之间的最大公约数。
这是迭代的思想
一会再写一种递归的思想,代码会更简洁,递归很重要!!!
//使用辗转相除法
#include<iostream.h>
using namespace std;
int main()
{
int n,m;//此时默认n是比m大的
int temp;
cin >> n >> m;
while(m != 0)//m == 0时说明前一步的temp == 0了,说明n % m == 0 ,那么m就是最大公约数
{
else if(n < m)
{
temp = n;
n = m;
m = temp;
}
else
{
temp = n % m;
n = m;
m = temp;
}
}
cout >> m;
}
递归的辗转相除法:
#include<iostream>
using namespace std;
//递归函数
int gcd(int a,int b)
{
if(a % b == 0)
{
return b;//一定是b,这个语句是递归出口,b是a % b的结果,代表的是最大公约数
}
else
{
return gcd(b,a % b);
}
}
//方法入口
int get(int numberA,int numberB)
{
if(numberA > numberB)
{
return gcd(numberA,numberB);
}
else
{
return gcd(numberB,numberA);
}
}
//计算最小公倍数
int Lcm(int a,int b)
{
return a * b / get(a,b);
}
int main()
{
int n,m;
cin >> n >> m;
cout << get(n,m)<< " "<< Lcm(n,m);
}
怎么求最小公倍数呢?
有一个公式:两个数的最小公倍数和最大公约数==两数之积
接下来使用更相减损术:
这个方法也是基于一个定理:
两个正整数a和b(a>b),它们的最大公约数等于a-b的差值c和较小数b的最大公约数。
所以代码可以写为这样:
#include<iostream>
using namespace std;
int main()
{
int n,m;
cin >> n >> m;
int temp;
if(n % m == 0)
{
cout << m;
return 0;
}
else
while(n % m != 0)
{
temp = n - m;
n = m;
// cout << n << endl;
m = temp;
// cout << m << endl << endl;
}
cout << m;
}
更相减损术也有递归的写法,递归会让代码量减少很多,所以挺好用的
#include <iostream>
using namespace std;
//递归函数
int gcd(int a,int b)
{
if(a % b == 0)
return b;
else
{
if(a > b)
return gcd(b,a-b);
else
return gcd(a,b-a);
}
}
int main()
{
int n,m;
cin >> n >> m;
cout << gcd(n,m);
return 0;
}
更相减损术不适用于两个数相差巨大的情况,比如1000 和 1,这样就要做 999 次运算
辗转相除法和更相减损术的结合加移位运算,因为移位运算的运算性能很高
对于给定的正整数 a 和 b,不难得到如下的结论。其中 gcb(a,b) 的意思是a,b的最大公约数函数:
当a和b均为偶数,gcb(a,b) = 2gcb(a/2, b/2) = 2gcb (a>>1, b>>1)
当a为偶数,b为奇数,gcb(a,b) = gcb(a/2, b) = gcb (a>>1, b)
当a为奇数,b为偶数,gcb(a,b) = gcb(a, b/2) = gcb (a, b>>1)
当a和b均为奇数,利用更相减损术运算一次,gcb(a,b) = gcb (b, a-b), 此时a-b必然是偶数,又可以继续进行移位运算。
比如计算10和25的最大公约数的步骤如下:
- 整数10通过移位,可以转换成求5和25的最大公约数
- 利用更相减损法,计算出25-5=20,转换成求5和20的最大公约数
- 整数20通过移位,可以转换成求5和10的最大公约数
- 整数10通过移位,可以转换成求5和5的最大公约数
- 利用更相减损法,因为两数相等,所以最大公约数是5
在两数比较小的时候,暂时看不出计算次数的优势,当两数越大,计算次数的节省就越明显。
#include<iostream>
using namespace std;
int gcd(int a,int b)
{
if(a % b == 0)
return b;
else
{
if(a & 1 == 0 && b & 1 == 0)
return gcd(a>>1,b>>1)<<1;
else if(a & 1 == 0 && b & 1 == 1)
return gcd(a>>1,b)<<1;
else if(a & 1 == 1 && b & 1 == 0)
return gcd(a,b>>1)<<1;
else
return gcd(b,a-b);
}
}
int main()
{
int n,m;
cin >> n >> m;
cout << gcd(n,m);
return 0;
}
这个方法真的是很厉害,但是有点难理解,对于原理的理解比较重要,但其实最常用的还是辗转相除法和更相减损术。
作者:Evinci
出处:https://www.cnblogs.com/evinci/p/17124004.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了