欧几里得算法的推导与证明 || 扩展欧几里德算法的解释说明

序言:

     当博主第一次见到欧几里德算法时,我是不屑一顾的,由于模板比较好背,所以也没有仔细研究过其中的数学原理.这段时间突然喜欢上了数学,碰巧同学讲了一下基础数论,就去听了一听. 由于博主数学基础和学习能力都比较差,没有立即消化其中的知识,于是研究了好几天,直到今天才有所进展,通过这篇博客希望大家能够认识到数学的精妙之处.

正文:

欧几里德算法的推导与证明:

     众所周知,欧几里德算法的定理可以表示为:
                                                       gcd(a,b)=gcd(b,a%b) g c d ( a , b ) = g c d ( b , a % b )
     但是这个定理是如何推导出来的呢?

首先我们可以假设 a=kb+r a = k ∗ b + r (其中的r代表着a/b的余数,也就是a%b的结果)

  1.首先我们假设d是a和b的最大公约数,则我们可以知道 a可以整除d,表示为a|b,b也可以整除d,表示为b|d,由于 r=akb r = a − k ∗ b 其中a是d的倍数,而且b也是d的倍数,那我们可以得到其实r也是d的倍数,换句话说r也是可以整除d.

  2.接下来我们假设d是b和r的最大公约数,则我们可以知道b可以整除d,表示为b|d,r也可以整除d,表示为r|d,由于 a=kb+r a = k ∗ b + r 其中b是d的倍数,而且r也是d的倍数,那我们可以得知其实a也是d的倍数,换句话说a也是可以整除d.

通过以上的充分必要式的证明方法,我们可以得到: gcd(a,b)=gcd(b,a%b) g c d ( a , b ) = g c d ( b , a % b )

接下来我们来看代码实现(递归) :

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

看起来十分简单,实则暗藏玄机…
首先我们需要考虑当 b=0 b = 0 时,为何要返回a呢.. 在解释之前,我要说明一点,只有当a > b时 算法才算正式开始进行运算,这是为什么呢?我们举个简单的例子,当 a=12,b=16 a = 12 , b = 16 时,我们在第二轮的时候惊奇的发现他递归的却是 gcd(16,12) g c d ( 16 , 12 ) ,这其实算是一种维护的过程,感叹第一写出这份代码人心思的缜密….回归正题,当我们发现 b=0 b = 0 时,也就是说上一轮的 a%b=0 a % b = 0 也就是说上一轮的a可以完全整除b,此轮的a则是上一轮的b提供的,所以将b返回即可。

我遇到的问题

在学习欧几里得的时候,我有一个疑惑,在我们刚才的推导过程:假设d是a和b的最大公约数,我们可以推导出 r ( a%b a % b )也可以整除d , 既然a,b,r都可以整除d,为什么我们的等式只能写作 gcd(a,b)=gcd(b,a%b) g c d ( a , b ) = g c d ( b , a % b ) 而不能写作 gcd(a,b)=gcd(a,a%b) g c d ( a , b ) = g c d ( a , a % b ) 呢? 在这个问题上,我思考了很久,终于得到了一定的理解… 首先我刚才说过 只有当 a>b a > b 的时候,算法才开始进行运算,所以说a在这里面是相对是最大的,b其次,而r是最小的…. 我说的可能太过绝对,以下为他们的具体关系:

                                                                  abr a ≥ b ≥ r

在我们每轮递归的过程中,希望值是越来越小的…其中a确永远是最大的…而且递归a也是没有意义的…因为我们最终要求的是最大公约数解.

代数形式的推导过程:

这里写图片描述
扩展欧几里德算法的解释说明:

    在学习完上面所讲的欧几里德算法之后,本节我们来讲一下 扩展欧几里得算法,欧几里德算法是用来做什么的呢?
    扩展欧几里德算法是用来在已知a, b求解一组x,y,使它们满足贝祖等式: ax+by=gcd(a,b) a x + b y = g c d ( a , b ) ,然后再求出现实所所需要的通解。由于证明这个等式成立的过程涉及到其他的数论知识,在学习基础的我们可以暂时把证明过程放在一边,权当这是成立的。

我们已知 ax1+by1=gcd(a,b) a ∗ x 1 + b ∗ y 1 = g c d ( a , b ) 根据欧几里德,我们可以得到:

                                         gcd(a,b)=gcd(b,a%b) g c d ( a , b ) = g c d ( b , a % b )

gcd(b,a%b)=bx2+(a%b)y2=bx2+(afloor(a/b)b)y2 g c d ( b , a % b ) = b ∗ x 2 + ( a % b ) ∗ y 2 = b ∗ x 2 + ( a − f l o o r ( a / b ) ∗ b ) ∗ y 2
我们最终可以得到:
y1=x2floor(a/b)y2,x1=y2 y 1 = x 2 − f l o o r ( a / b ) ∗ y 2 , x 1 = y 2

接下来我们来看代码实现(递归) :

int exGcd(int a,int b,int &x,int &y)
{
    if(b==0)
    {
        x=1;y=0;
        return a;
    }
    int r=exGcd(b,a%b,x,y);
    int t=x;
    y=t-a/b*y;
    return r;
}

现在我们考虑一下递归的终点…..当 b=0 b = 0 我们为何要 x=1 x = 1 , y=0 y = 0 呢…
首先我们知道贝祖等式 ax+by=gcd(a,b) a ∗ x + b ∗ y = g c d ( a , b ) 其中 agcd(a,b) a ≥ g c d ( a , b ) b=0 b = 0 x=1 x = 1 是必然的,满足最终 a=gcd(a,b) a = g c d ( a , b ) ,而y的取值..由于 b=0 b = 0 所以y可以取任何值…但是我们最终要求的最小解..所以将其赋值为零…
通过以上的运算过程….我们把 ax+by=gcd(a,b) a ∗ x + b ∗ y = g c d ( a , b ) 的其中一组解解出来了, 仅仅是其中一组解。对于已经得到的解x1, y1,我们便可以求出通解。
通解计算公式:

x=x0+kt,y=y0+kt x = x 0 + k ∗ t , y = y 0 + k ∗ t

我们假设 x=x0+kt x = x 0 + k ∗ t ,将其带入到 ax+by=gcd(a,b) a ∗ x + b ∗ y = g c d ( a , b ) ,我们可以得到 y=y0ak/bt; y = y 0 − a ∗ k / b ∗ t ;
而我们要保证y也为整数的话必须保证a * k /b也为整数,我们不妨令 k=b/gcd(a,b) k = b / g c d ( a , b )
所以通解为:
                x=x0+b/gcd(a,b)t x = x 0 + b / g c d ( a , b ) ∗ t
                y=y0a/gcd(a,b)t; y = y 0 − a / g c d ( a , b ) ∗ t ;
其中的t就是x,y满足贝祖等式时的周期。

我需要讲的最后一个问题:

      求任何数字n在一定周期t中最小正整数:

int ans = ((n % t)+t) % t;

有关题目:POJ 1601

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值