欧几里得算法与扩展算法

欧几里得算法(Euclidean Algorithm)

欧几里得算法(也称为辗转相除法)是一种查找两个正整数 a a a b b b 的最大公约数的方法。
最大公约数(GCD - Greatest Common Divisor),另一个名字是HCF(Highest Common Factor)。

例子1:令 a = 210 a=210 a=210 b = 45 b=45 b=45
210 ‾ = 45 ‾ ∗ 4 + 30 ‾ 45 ‾ = 30 ‾ ∗ 1 + 15 ‾ 30 ‾ = 15 ‾ ∗ 2 + 0 ‾ \begin{align} \underline{210} &= \underline{45}*4+\underline{30}\\ \underline{45} &= \underline{30}*1+\underline{15}\\ \underline{30} &= \underline{15}*2+\underline{0} \end{align} 2104530=454+30=301+15=152+0

其中,下划线数字可以认为是一些固定变量,而上述式子中的 4 4 4, 1 1 1, 2 2 2为这些固定变量的系数。
注意,当式子最后一个余数为0的时候,此时计算过程就结束了。

若采用编程语言进行表述,如下提供几个例子(注意输入时,一般假设 a > b > 0 a>b>0 a>b>0):
(1)Python函数(请注意缩进关系):

def gcd(a, b):
    while b:
        a, b = b, a%b
    return a

(2)C语言函数:

int hcf(int a, int b) {
    if (b != 0) return hcf(b, a % b);
    else return a;
}

另外,最小公倍数(LCM, Lowest/Least Common Multiple)与最大公约数紧密相关,如果已经计算出 a a a b b b两个整数的最大公约数记为 c c c,那么 l c m ( a , b ) = a / c ∗ b = a ∗ b / c lcm(a,b)=a/c*b=a*b/c lcm(a,b)=a/cb=ab/c

扩展欧几里得算法(Extended Euclidean Algorithm)

除了计算 a a a b b b两个整数的最大公约数,此算法还能找到整数 x x x y y y(其中一个很可能是负数)。通常谈到最大公因子时, 我们都会提到一个非常基本的事实:给予二整数 a a a b b b, 必存在有整数 x x x y y y使得 a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b)
扩展欧几里得算法还能够用于求解数论中乘法逆元(主要应用于密码学中)。

例子1续:令 a = 210 a=210 a=210 b = 45 b=45 b=45
已知例子1中正向过程求得 g c d ( 210 , 45 ) = 15 gcd(210,45)=15 gcd(210,45)=15,以下提供逆向过程:
15 ‾ = 30 ‾ − 15 ‾ = 30 ‾ − [ 45 ‾ − 30 ‾ ] = 30 ‾ ∗ 2 − 45 ‾ = [ 210 ‾ − 45 ‾ ∗ 4 ] ∗ 2 − 45 ‾ = 210 ‾ ∗ 2 − 45 ‾ ∗ 9 \begin{align} \underline{15} &= \underline{30}-\underline{15} \\ &= \underline{30} - [\underline{45}-\underline{30}]\\ &= \underline{30}*2 - \underline{45}\\ &= [\underline{210}-\underline{45}*4]*2 - \underline{45}\\ &= \underline{210}*2-\underline{45}*9\\ \end{align} 15=3015=30[4530]=30245=[210454]245=2102459
此时,便得到 x = 2 x=2 x=2,而 y = − 9 y=-9 y=9
在逆向过程中,首先提取一个最大公约数放在等式左边,接着通过正向过程中的等式代换 15 ‾ \underline{15} 15,接着整理等式右侧;再代换 30 ‾ \underline{30} 30,接着整理等式右侧;最后便得到形如 a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b)的式子。

例子2:令 a = 7 a=7 a=7 b = 26 b=26 b=26,求取 x = a − 1 mod  b = 7 − 1 mod  26 x=a^{-1}\text{mod}\space b=7^{-1}\text{mod}\space 26 x=a1mod b=71mod 26
本题意思:求取 7 7 7相对于模 26 26 26乘法运算的逆元(即乘法逆元)。
前提: g c d ( a , b ) = 1 gcd(a,b)=1 gcd(a,b)=1时,才存在乘法逆元,即 a a a b b b需要互为素数。
首先,提供正向过程(即应用辗转相除法):
26 ‾ = 7 ‾ ∗ 3 + 5 ‾ 7 ‾ = 5 ‾ ∗ 1 + 2 ‾ 5 ‾ = 2 ‾ ∗ 2 + 1 ‾ \begin{align} \underline{26} &= \underline{7}*3+\underline{5}\\ \underline{7} &= \underline{5}*1+\underline{2}\\ \underline{5} &= \underline{2}*2+\underline{1} \end{align} 2675=73+5=51+2=22+1
其中,下划线数字可以认为是一些固定变量,而上述式子中的 3 3 3, 1 1 1, 2 2 2为这些固定变量的系数。
注意,当式子最后一个余数为1的时候,此时计算过程就结束了(注意与例1的区别)。
接着,提供逆向过程(与例1续稍有不同):
1 ‾ = 5 ‾ − 2 ‾ ∗ 2 = 5 ‾ − [ 7 ‾ − 5 ‾ ] ∗ 2 = 5 ‾ ∗ 3 − 7 ‾ ∗ 2 = [ 26 ‾ − 7 ‾ ∗ 3 ] ∗ 3 − 7 ‾ ∗ 2 = 26 ‾ ∗ 3 − 7 ‾ ∗ 11 = 26 ‾ ∗ 3 + 7 ‾ ∗ 15 \begin{align} \underline{1} &= \underline{5}-\underline{2}*2 \\ &= \underline{5} - [\underline{7}-\underline{5}]*2\\ &= \underline{5}*3 - \underline{7}*2\\ &= [\underline{26}-\underline{7}*3]*3 - \underline{7}*2\\ &= \underline{26}*3-\underline{7}*11\\ &= \underline{26}*3+\underline{7}*15\\ \end{align} 1=522=5[75]2=5372=[2673]372=263711=263+715
此时,便得到 x = 15 x=15 x=15,而 y = 3 y=3 y=3
在逆向过程中,首先将 1 ‾ \underline{1} 1放在等式左边,接着通过正向过程中的等式代换 2 ‾ \underline{2} 2,接着整理等式右侧;再代换 5 ‾ \underline{5} 5,接着整理等式右侧;最后便得到形如 a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b)的式子。
另外,由于当前问题的乘法是模乘、加法是模加,所以最后得 − 11 mod  26 = 15 -11\text{mod}\space 26=15 11mod 26=15
另外,也可以看到 7 ∗ 15 mod  26 = 1 7*15\text{mod}\space 26=1 715mod 26=1,即 7 7 7 15 15 15相对于模 26 26 26乘法运算互为乘法逆元。
注意,乘法逆元属于初等数论(讨论整数的计算性质与特殊规律)中的知识,主要应用于密码学等技术(密码学中的数据必须是确定的数值,不能采用浮点数或小数进行表示,即使采用字符串表示小数,那也是一种整型或整数的表示形式)中。

若采用编程语言进行表述,如下提供几个例子:
(1)Python函数(请注意缩进关系):

def ext_euclid(a, b):     
    if b == 0:         
        return 1, 0, a     
    else:         
        x, y, q = ext_euclid(b, a % b)      
        x, y = y, (x - (a // b) * y)         
        return x, y, q

(2)C语言函数:

 int gcdEx(int a,int b,int*x,int*y)
{
    if(b==0)
    {
        *x=1,*y=0 ;
        return a ;
    }
    else 
    {
        int r=gcdEx(b,a%b,x,y);
        int t=*x ;
        *x=*y ;
        *y=t-a/b**y ;
        return r ;
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值