zl程序教程

您现在的位置是:首页 >  其他

当前栏目

密码学简单数论笔记(2):最大公约数、扩展欧几里得算法和最小公倍数

2023-04-18 15:28:00 时间

  
参考资料:
1.https://www.bilibili.com/video/BV1x3411s7Sy/?spm_id_from=333.788&vd_source=e66dd25b0246f28e772d75f11c80f03c
2.http://t.csdn.cn/diQ27
2.余红兵:《数学奥林匹克小丛书(第二版)高中卷10————数论》

最大公约数

  

设a,b∈Z,如果d∈Z且d|a,d|b,则称d是a和b的公因子(公约数)。
若d>=0,且a和b的所有公因子都整除d,则称d是a和b的最大公约数,记作gcd(a,b).

之前CSDN上我也写过一篇gcd筛:
https://blog.csdn.net/hustle28214/article/details/128601837?spm=1001.2014.3001.5501

互素

设a,b∈Z,若gcd(a,b)=1,则称a和b互素。
互素的a,b公因子仅有±1,该条件可反推出a,b两数互素.

根据定义有结论:
设gcd(a,b)=d,则存在q1,q2∈Z,使得a=q1d,b=q2d,且gcd(q1,q2)=1.

若gcd(q1,q2)=t>1,则gcd(a,b)=td>d,与“最大”矛盾.
  

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

  

设a>=b>=0,求gcd(a,b)
对于上述条件下的a,b,有a=qb+r;
b=0时,gcd(a,0)=a
b>0时,gcd(a,b)=gcd(b,r)=gcd(r1,r2)

gcd(a,b)=gcd(b,r)这条推广有必要演示一下:
gcd(40,3)=1
gcd(40,3)=gcd(3,1)=gcd(1,0)=1
依次如此操作直到见到0
  

int gcd(int x, int y)
{
    int r = x % y;
    while (r != 0)
    {
        x = y;
        y = r;
        r = x % y;
    }    
return y;//最大公约数实现
 
}

扩展欧几里得算法

  

(重要)定理5-1(最大公约数表示定理)(裴蜀定理)

  

设a,b∈Z,d=gcd(a,b),则存在s,t∈Z,使得as+bt=d.
特别地:gcd(a,b)=1————as+bd=1(充要)
推论:d|v————as+bt=v
证明:
设b>=a,b=ax1+r1,那么b%a后b=r1.
重复辗转相除直至余数为0。
b=ax1+r1,
a=r1x2+r2,
......,
rk-3=rk-2xk-1+rk-1(2)
rk-2=rk-1xk+rk,(1)
rk-1=rkxk+1+rk+1.

此时rk+1=0(余数).由此得出rk=d(最大公约数).将此式代入(1)式,移项得到d=rk-2-rk-1xk.
将此式与(2)式联立,得到d=rk-2-(rk-3-rk-2xk-1)xk.
展开,得到d=m1rk-2-n1rk-3.
上述所有提及皆为整数,则m1(1-xk-1xk),n1(-xk)必为整数。
相同的操作可以重复做,不断带入之前的式子可以发现最后可以化成d=mka+nkb。
而显然mk,nk为整数。
证毕。

对于第二条“特别地”的证明如下:
假设gcd(a,b)!=1.
那么,
将a表示为k1gcd(a,b)=a,
b=k2
gcd(a,b).
代入as+bd=1:
k1*gcd(a,b)*s+k2*gcd(a,b)*r=1.
即,(k1s+k2r)=1/gcd(a,b)
那么右式取值区间为(0,1),显然无法满足整数解性质.
所以gcd(a,b)=1才能使as+bd=1有整数解。
想一想,如果要证其必要性,则假设as+bd=1没有整数解,右式=1,也必定存在s,d∈Z使得方程有解.
  
第三条推论自不必说,v是d的整数倍.
所以,扩欧相对于欧几里得算法的扩展性就是:使用欧几里得算法时,利用余数和商向上迭代出sn,tn。这同样也是在计算二元一次不定方程.
  
通过扩欧我们可以找到判断二元一次不定方程是否有整数解的方法:

对于方程ax+by=z,只有满足gcd(a,b)|z,方程才有整数解.
  

最小公倍数

  

设a,b∈Z,若m∈Z分别是a和b的倍数,m称为a和b的公倍数.
记a,b的最小公倍数为lcm(a,b),若m是a和b所有正的公倍数中最小,m称作a和b的最小公倍数.
lcm(a,b)=ab/gcd(a,b).

  
我在CSDN那篇上写“最小公倍数的求算依赖于最大公约数的求算”,其实这有些以偏概全,求最小公倍数的算法并不止这一种。下面就记录一下这种不需要找最大公约数的神奇算法(更相增益术/更相减损术):
设有两正整数0<a<b.
  
a更小,a自加成2a;此时若发现b更小,b自加,成2b;...;若发现a更小,a自加,直到2k*a=2k-1*b.那么2ka就等于lcm(a,b)。
  

int lcm(int a,int b)
{
    while(a!=b)
    {
        if(a<b)
        a+=a;
        else if(b<a)
        b+=b;

    }
    return a;
}