Day13:拓展欧几里得算法

Day13:拓展欧几里得算法

一. 问题背景:

计算a、b两个整数的最大公约数。

二. 解决思路:

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

        辗转相除法, 又名欧几里得算法(Euclidean algorithm),是求最大公约数的一种方法。它的具体做法是:用较大数除以较小数,再用出现的余数(第一余数)去除除数,再用出现的余数(第二余数)去除第一余数,如此反复,直到最后余数是0为止。如果是求两个数的最大公约数,那么最后的除数就是这两个数的最大公约数。

   Day13:拓展欧几里得算法_第1张图片  

              Day13:拓展欧几里得算法_第2张图片

2. 更相减损法:

        第一步:任意给定两个正整数;判断它们是否都是偶数。若是,则用2约简;若不是则执行第二步。
              第二步:以较大的数减较小的数,接着把所得的差与较小的数比较,并以大数减小数。继续这个操作,直到所得的减数和差相等为止。
              则第一步中约掉的若干个2与第二步中等数的乘积就是所求的最大公约数。 

             Day13:拓展欧几里得算法_第3张图片

3. Stein算法:

        辗转相除法是计算两个数最大公约数的传统算法,无论从理论还是从实际效率上都是很好的。但是却有一个致命的缺陷,这个缺陷在素数比较小的时候一般是感觉不到的,只有在大素数时才会显现出来:一般实际应用中的整数很少会超过64位(当然已经允许128位了),对于这样的整数,计算两个数之间的模是很简单的。对于字长为32位的平台,计算两个不超过32位的整数的模,只需要一个指令周期,而计算64位以下的整数模,也不过几个周期而已。但是对于更大的素数,这样的计算过程就不得不由用户来设计,为了计算两个超过64位的整数的模,用户也许不得不采用类似于多位数除法手算过程中的试商法,这个过程不但复杂,而且消耗了很多CPU时间。对于现代密码算法,要求计算128位以上的素数的情况比比皆是,比如说RSA加密算法至少要求500bit密钥长度,设计这样的程序迫切希望能够抛弃除法和取模。

        Stein算法很好的解决了辗转相除法中的这个缺陷,Stein算法只有整数的移位和加减法。下面就来说一下Stein算法的原理:

            1. 若a和b都是偶数,则记录下公约数2,然后都除2(即右移1位);

            2. 若其中一个数是偶数,则偶数除2,因为此时2不可能是这两个数的公约数了

            3. 若两个都是奇数,则a = |a-b|,b = min(a,b),因为若d是a和b的公约数,那么d也是|a-b|和min(a,b)的公约数。

        Stein算法比辗转相除法更加快速,简易。它与每一次进行更相减损法得到的结果似乎存在着微妙的联系,通过下面的比较,可以发现两种算法之间的联系。

                        Day13:拓展欧几里得算法_第4张图片

4. 扩展欧几里得算法:

        拓展欧几里得算法是欧几里得算法的扩展。除了计算a、b两个整数的最大公约数,此算法还能找到整数x、y(其中一个很可能是负数)。通常谈到最大公因子时, 我们都会提到一个非常基本的事实(详见注1):若设a,b是整数,则存在整数x,y,使得ax+by=gcd(a,b)。有两个数a,b,对它们进行辗转相除法,可得它们的最大公约数——这是众所周知的。然后,收集辗转相除法中产生的式子,倒回去,可以得到ax+by=gcd(a,b)的整数解。

 

                Day13:拓展欧几里得算法_第5张图片

        拓展欧几里得算法证明:转自:https://blog.csdn.net/lincifer/article/details/49391175

                Day13:拓展欧几里得算法_第6张图片

三. 算法实现:

#模拟矩阵表示
def gcd(x, y):
    u0, v0 = 1, 0
    u1, v1 = 0, 1
    while y:
        q = x // y
        u0, u1 = u1, u0 - q * u1
        v0, v1 = v1, v0 - q * v1
        x, y = y, x % y     #gcd(x, y) = gcd(y, x%y)
    return x, u0, v0

#print(gcd(2*3*7*9*11, 6*12*13))
print(gcd(30, 47))


#递归
def ext_euclid(a, b):     
    if b == 0:         
        return 1, 0, a     
    else:
        # q = gcd(a, b) = gcd(b, a%b)  欧几里得算法          
        x, y, q = ext_euclid(b, a % b)      
        x, y = y, (x - (a // b) * y)      
        return x, y, q

print(ext_euclid(47,30))

附录:

贝祖定理/裴蜀定理:

        裴蜀定理说明了对任何整数 a、b和它们的最大公约数 d ,关于未知数 x 和 y 的线性丢番图方程(称为裴蜀等式)。其中丢番图方程又名不定方程、整系数多项式方程,是变量仅容许是整数的多项式等式;番图问题有数条等式,其数目比未知数的数目少;丢番图问题要求找出对所有等式都成立的整数组合。对丢番图问题的数学研究称为丢番图分析。

      Day13:拓展欧几里得算法_第7张图片

        其中,d|a意为d整除a(a可以被d整除),⌊a/s⌋意为(a/s)向下取整。

        原作者最后一行应更正为d | (ax1+by1)。

        引自:https://blog.csdn.net/discreeter/article/details/69833579

 

你可能感兴趣的:(算法100days)