终于开始正式写数论了,之前的快速幂和进制转化不算,莫名有些激动。
废话不多说,我们直接
进入正题!#
还是老样子,先搞明白定义
gcd 最大公因数
lcm 最小公倍数
此外,为了方便,规定 gcd(0,a)=a
a×b=gcd(a,b)×lcm(a,b)
你一定很好奇这是怎么来的,对吧?
别急,这就向你解释,但在这里,我们要插入一个小小的定理——唯一分解定理
半路杀出的唯一分解定理#
看着很难,其实很好理解
就是一个正整数都可以拆成 ak11×ak22×ak33×ak44… 的形式,有且仅有这一种形式
其中 a1,a2… 都是质数,k1,k2… 都是指数
说白了就是质因数分解
比如说 252=23+32+71
在这里,如果一个数 a 是另一个数 b 的因数,a≠b,那么 a 分解质因数所得的 k1 , k2 都小于等于 b 所对应的 k1 , k2
比如 84 是 252 的因数
84=22+31+71
很显然,是符合我们上面的结论的
同理,如果一个数 a 是另一个数 b 的倍数,a≠b,那么 a 分解质因数所得的 k1 , k2 都大于等于 b 所对应的 k1 , k2
比如 252 是 84 的倍数
84=22+31+71252=23+32+71
很显然,也是符合的
如果
a=dk11+dk22+dk33+dk44…b=dj11+dj22+dj33+dj44…
一个数 c=dg11+dg22+dg33+dg44… 是 a 和 b 的公因数
由上面的结论可得 gi≤min(ki,ji)
如果要求 gcd(a,b)
那么 gcd(a,b)=dmin(k1,j1)1+dmin(k2,j2)2+dmin(k3,j3)3+dmin(k4,j4)4…
同理,一个数 c=dg11+dg22+dg33+dg44… 是 a 和 b 的公倍数,则gi≥max(ki,ji)
要求 lcm(a,b),则lcm(a,b)=dmax(k1,j1)1+dmax(k2,j2)2+dmax(k3,j3)3+dmax(k4,j4)4…
所以 gcd(a,b)×lcm(a,b)=dmax(k1,j1)+min(k1,j1)1+dmax(k2,j2)+min(k2,j2)2+dmax(k3,j3)+min(k3,j3)3+dmax(k4,j4)+min(k4,j4)4…
也就是 gcd(a,b)×lcm(a,b)=dk1+j11+dk2+j22+dk3+j33+dk4+j44…=a×b
所以我们证明了结论 a×b=gcd(a,b)×lcm(a,b)
求 gcd ——欧几里得算法#
欧几里得算法,其实就是辗转相除法
gcd(a,b)=gcd(b,amodb)
如何证明它的正确呢?
这里要用到弱化版本——更相减损术
同样半路杀出来的更相减损术#
gcd(a,b)=gcd(a−b,b)
如果c∣a,c∣b,则a=cx,b=cy,那么a−b=c(x−y),所以c∣a−b
也就是说 c 如果是 a 和 b 的公因数,那它也一定是 a−b 的公因数,所以 gcd(a,b)=gcd(a−b,b) 是成立的
回归求 gcd#
我们利用更相减损术继续往下推
gcd(a,b)=gcd(a−b,b)=gcd(a−b−b,b)=gcd(a−b−b−b,b)=…
a 一直减 b,减到最后就成为了 gcd(amodb,b)
所以 gcd(a,b)=gcd(amodb) ,但为了方便递归,我们将参数换一下,改为 gcd(b,amodb)
求 gcd
int gcd(int a,int b)
{
if(b==0) return a;
return gcd(b,a%b);
}
求 lcm ,可以直接用 agcd(a,b)×b 来完成
这里打好基础,后面的扩展欧几里得算法才能学会
本文到这里就结束了,喜欢的话可以支持一下ヾ(≧▽≦*)o
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效