最小公倍数的求法

  • 什么是最小公倍数? 

最小公倍数是指两个或多个整数共有的最小正整数倍数。

  • 如何求一组数据的最小公倍数(Least Common Multiple,简称LCM)? 

       LCM = 这组数据的公倍数   \div  这组数据的最大公约数 (Greatest Common Divisor,简称GCD)

例如:两个数a和b,它们的最小公倍数lcm(a, b)可以通过它们的乘积除以它们的最大公约数gcd(a, b)来得到,即:lcm(a,b) =  \frac{a*b}{gcd(a, b))}  ,所以求最小公倍数的问题重点就转换成了求最大公约数。

  • 如何求最大公约数?欧几里得算法: gcd(a,b)

欧几里得算法,又称为“辗转相除”法,顾名思义, 这个算法的核心思想就是不断的去除。它是迄今为止已知的最古老的算法,距今(2024年)已经有2324年了,这个算法可用于快速计算两个数字的最大公约数的。

定理:a 和 b两个整数的最大公约数等于 b 与  a%b 的最大公约数。

通过定理的表述,我们发现,问题规模从[b,a] 缩小到了为了[b, a%b],即问题规模从原始规模缩小到了原始规模的子规模,但是问题的解没有变,也就是说,子规模中蕴含着原始问题的解。

所以,我们要证明两点:

第一: 在子规模中包含原始规模的解;

第二:在子规模中找到的答案就是最大公约数,而不仅仅是公约数之一。

证明问题一:

如果我们能证明 a 和 b 的最大公约数,同时也能被 a % b 整除 (是a%b的因子),那么就可以说原始规模的问题的解是包含在子规模中的。

              设 a和b 的最大公约数 为c :即 c = gcd(a,b), 则: a = cx, b = cy;

              假设: a % b = r; 

              那么:r = a - kb = cx - kcy = c(x-ky) 

              所以:c 也是 r 的因子。

证明问题二:

如果我们想证明 gcd(b, a%b ) 得到的就是最大公约数,那么只要证明 b 和 (a%b)除了c之外再无公约数即可,又因为b = cy, a%b = c(x-ky) , 即只要能能证明 y 和 (x-ky)互为素数即可。

             假设: gcd(x-ky, y) = d;

             则 y = nd,

             x-ky = md ; \Rightarrow  x = md+ky \Rightarrow x = (m+kn)d;

             所以,a 和 b 可以表示成: a = cd(kn +m), b = cdn,  进而可知:gcd(a,b) >= cd ,

             又因为 gcd(a,b) = c, 

             所以 d=1, y 和 (x-ky)的公约数为1, 说明y 和(x-ky) 互为素数。

 题目1:2520是最小的能够被1到10整除的正数。最小的能够被1到20整除的正数是多少?

题目分析:

根据题目描述,就是要找到1到20的最小公倍数。

代码实现:

#include <stdio.h>

//求整数a 和 b 的最大公约数
int gcd(int a, int b){
    if(b == 0) return a;
    return gcd(b, a%b);
}


//求整数a 和 b 的最小公倍数
long lcm(long a, long b){
    return a*b / gcd(a, b);
}

//求1到20 的最小公倍数
int main(){
    long long ans = 1;
    for(int i = 2; i <= 20; i++) ans = lcm(ans, i);
    printf("%lld\n", ans);
    return 0;
}

小技巧:

在上述代码中,函数 long lcm(long a, long b) ,有两点需要注意,第一,为了不出现数据溢出现象,数据类型定义为long, 第二, 同样是为了不出现数据溢出, a*b/gcd(a,b)  这个运算语句,应该改为先 a /gcd(a, b) * b,  即先执行除法再做乘法,以免先乘法生产一个超出数据范围的大数据。

//求整数a 和 b 的最小公倍数
long lcm(long a, long b){
    return a / gcd(a, b) * b;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

xinran0703

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

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

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

打赏作者

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

抵扣说明:

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

余额充值