今天终于弄懂了扩展欧几里德算法,有了自己的理解,觉得很神奇,就想着写一篇博客。

在介绍扩展欧几里德算法之前,我们先来回顾一下欧几里德算法。

欧几里德算法(辗转相除法):

  辗转相除法求最大公约数,高中就学了,但当时知其然不知其所以然,直到大学才真正理解它的精髓。

  理解辗转相除,关键在于理解 gcd(a,b)==gcd(b,a%b)

  那么怎么去理解呢?下面是我的理解:

    首先对于非负整数a,b,一定可以写成 a=k*b+r(r<b) 的形式

    令 g=gcd(a,b) ,则有 g|a ,即 g|(k*b+r)

            又 g|b ,所以 g|r

    当然,只证得 g 同时整除 b 和 r 依然不能得出 g==gcd(b,r),还可能是gcd(b,r)>g 。

    于是我们假设存在 g‘>g(故g'不可能是 a,b 的公约数)

            使得 g'|b 且 g'|r

           则有 g'|(k*b+r) 即 g'|a

           → g' 是 a,b 的公约数,矛盾。

    故 gcd(a,b)==gcd(b,r)(其中 r==a%b) 得证。

  下面贴出欧几里德算法的递归和非递归代码:

 //递归欧几里德算法
int gcd(int a,int b)
{
return b==?a:gcd(b,a%b);
}
 //非递归欧几里德算法
int gcd(int a,int b)
{
int t;
while(b){
t=b;
b=a%b;
a=t;
}
return a;
}

  值得注意的是:

    1、任意正整数和 0 的最大公约数为正整数本身。

    2、即使参数 a<b ,经过一次递归或循环之后,a,b 会自动交换,故开头不需要加 if(a<b)swap(a,b); 语句。

扩展欧几里德算法:

  扩展欧几里德算法其实就是为了求出 ax+by=gcd(a,b) 的一个整数解 (x0,y0) ,然后就能得出全部整数解为 (x0+k*b,y0-k*a) 。

  递归实现

     扩展欧几里德算法的递归实现是基于递归求gcd的过程,它会在gcd函数递归完返回的时候逐步解出一个整数解(x,y) 。

     让我们来简单模拟一下 gcd(a,b) 递归返回的过程(数学归纳法得出递推公式)

       ①在gcd递归到最深处(倒是第一层)的时候,即此时 b0==0 ,可得出方程 a0x+b0y=gcd(a,b) (gcd(a,b)==gcd(a0,b0)==gcd(a1,b1)==…==a0)的一组整数解为x0=1,y0=0。

       ②假设返回到倒数第 k 层时方程 akx+bky=gcd(a,b) 的一组整数解为 xk , yk

        又设返回到倒数第 k+1 层时方程 ak+1x+bk+1y=gcd(a,b) 的一组整数解为 xk+1 , yk+1

        则有 akxk+bkyk=ak+1xk+1+bk+1yk+1 其中 ak==bk+1 , bk=ak+1%bk+1

        不妨令 xk+1=yk   yk+1=xk-ak+1/bk+1*yk

     下面贴出递归代码:

 //递归扩展欧几里得算法
int exgcd(int a,int b,int&x,int&y)
{
if(b==){
x=,y=;
return a;
}
int r=exgcd(b,a%b,y,x);
y-=a/b*x;
return r;
}

  非递归实现

    个人感觉扩展欧几里德算法的非递归方式理解起来更为简单。

    我们就从一个具体的例子入手吧。

        若 a=30 , b=47 , 则 gcd(a , b)=1,那么就是要求解一次不定方程 30x+47y=1 的整数解。

        由已知,我们有

        

           观察上述矩阵,第三列的元素变换过程恰好是辗转相除法求最大公约数的过程。

        他们的每一步的变换形式(行变换)可用如下通式表示:

              

        当第 2 行 3 列的元素为 0 时,第 1 行 3 列的元素即为 gcd(a , b)。

        故最终能得出一组整数解 (x , y)=(11 , -7) 满足 30x+47y=1 。

        于是我们可以在非递归欧几里德算法的基础上写出非递归的扩展欧几里德算法,代码如下:

 //非递归扩展欧几里得算法
int exgcd(int a,int b,int&x,int&y)
{
int m=,n=,t;
x=,y=;
while(b){
t=m,m=x-a/b*m,x=t;
t=n,n=y-a/b*n,y=t;
t=b,b=a%b,a=t;
}
return a;
}

写到这里算是终于写完了。

这是我写的第一篇博客,本来旨在用最简洁的语言描述最核心的思想,但貌似……可能……大概……与预期有点不符...

我希望通过写博客记录一下自己的想法,即使日后忘记也能一看便知。当然,如果能帮助别人深入理解,那就再好不过了。

最后,如果各位发现文中的错误、有什么建议或者有一些自己的想法,都欢迎在评论区提出。

扩展欧几里德算法(递归及非递归实现c++版)的更多相关文章

  1. 汉诺塔算法的递归与非递归的C以及C++源代码

    汉诺塔(又称河内塔)问题其实是印度的一个古老的传说. 开天辟地的神勃拉玛(和中国的盘古差不多的神吧)在一个庙里留下了三根金刚石的棒,第一根上面套着64个圆的金片,最大的一个在底下,其余一个比一 个小, ...

  2. 回溯算法 DFS深度优先搜索 (递归与非递归实现)

    回溯法是一种选优搜索法(试探法),被称为通用的解题方法,这种方法适用于解一些组合数相当大的问题.通过剪枝(约束+限界)可以大幅减少解决问题的计算量(搜索量). 基本思想 将n元问题P的状态空间E表示成 ...

  3. C#实现(递归和非递归)高速排序和简单排序等一系列排序算法

        本人由于近期工作用到了一些排序算法.就把几个简单的排序算法.想冒泡排序,选择排序,插入排序.奇偶排序和高速排序等整理了出来,代码用C#代码实现,而且通过了測试.希望能给大家提供參考.     ...

  4. 汉诺塔算法c++源代码(递归与非递归)[转]

     算法介绍: 其实算法非常简单,当盘子的个数为n时,移动的次数应等于2^n - 1(有兴趣的可以自己证明试试看).后来一位美国学者发现一种出人意料的简单方法,只要轮流进行两步操作就可以了.首先把三根柱 ...

  5. 欧几里德与扩展欧几里德算法 Extended Euclidean algorithm

    欧几里德算法 欧几里德算法又称辗转相除法,用于计算两个整数a,b的最大公约数. 基本算法:设a=qb+r,其中a,b,q,r都是整数,则gcd(a,b)=gcd(b,r),即gcd(a,b)=gcd( ...

  6. ACM_扩展欧几里德算法

    <pre name="code" class="cpp">/* 扩展欧几里德算法 基本算法:对于不完全为 0 的非负整数 a,b,gcd(a,b)表 ...

  7. C语言实现 二分查找数组中的Key值(递归和非递归)

    基本问题:使用二分查找的方式,对数组内的值进行匹配,如果成功,返回其下标,否则返回 -1.请使用递归和非递归两种方法说明. 非递归代码如下: #include <stdio.h> int ...

  8. poj2115-C Looooops(扩展欧几里德算法)

    本题和poj1061青蛙问题同属一类,都运用到扩展欧几里德算法,可以参考poj1061,解题思路步骤基本都一样.一,题意: 对于for(i=A ; i!=B ;i+=C)循环语句,问在k位存储系统中循 ...

  9. poj1061-青蛙的约会(扩展欧几里德算法)

    一,题意: 两个青蛙在赤道上跳跃,走环路.起始位置分别为x,y. 每次跳跃距离分别为m,n.赤道长度为L.两青蛙跳跃方向与次数相同的情况下, 问两青蛙是否有方法跳跃到同一点.输出最少跳跃次数.二,思路 ...

随机推荐

  1. Flutter学习笔记(5)--Dart运算符

    如需转载,请注明出处:Flutter学习笔记(5)--Dart运算符 先给出一个Dart运算符表,接下来在逐个解释和使用.如下:                            描述       ...

  2. ORM的记录添加和删除

    记录查询包括:跨表查询(重点),  分组查询,聚合查询,  F与Q查询 查询之前需要先添加数据: 一对多添加: def addrecord(request): Book.objects.create( ...

  3. Vue快速学习_第二节

    表单输入绑定(v-model) v-model 指令在表单 <input>.<textarea> 及 <select> 元素上创建双向数据绑定(注意只在表单这几个可 ...

  4. 基于SpringBoot的WEB API项目的安全设计

    SpringBoot的开箱即用功能,大大降低了上手一个WEB应用的门槛,友好的REST接口支持,在SpringCloud微服务体系中可编程性大大提高,本篇基于一个面向企业调用方用户的WEB API项目 ...

  5. BZOJ3033 太鼓达人题解

    太鼓达人 时间限制: 1 Sec  内存限制: 128 MB 题目描述 七夕祭上,Vani牵着cl的手,在明亮的灯光和欢乐的气氛中愉快地穿行.这时,在前面忽然出现了一台太鼓达人机台,而在机台前坐着的是 ...

  6. .NET多线程之线程安全,Lock(锁)、Monitor(同步访问)、LazyInitializer(延迟初始化)、Interlocked(原子操作)、static(静态)构造函数、volatile、

    1.什么是线程安全 线程安全是编程中的术语,指某个函数.函数库在多线程环境中被调用时,能够正确地处理多个线程之间的共享变量,使程序功能正确完成.一般来说,线程安全的函数应该为每个调用它的线程分配专门的 ...

  7. vue自定义表单生成器,可根据json参数动态生成表单

    介绍 form-create 是一个可以通过 JSON 生成具有动态渲染.数据收集.验证和提交功能的表单生成器.并且支持生成任何 Vue 组件.结合内置17种常用表单组件和自定义组件,再复杂的表单都可 ...

  8. Appium+python自动化(二十一)- 让猴子按你指令大闹手机,让你成为耍猴高手 - Monkey(猴子) - MonkeyScript(超详解)

    简介 一年一度的暑假如期而至,每年必不可少的,便是<西游记>这部经典电视连续剧的播出,作为一名90后,对于这部经典剧的情谊,就是观看已成为一种习惯.依然深刻的记得,小时候妈妈为了催促我睡觉 ...

  9. dubbo框架设计学习

    1.整体设计 (1)架构图 图例说明: 图中左边淡蓝背景的为服务消费方使用的接口,右边淡绿色背景的为服务提供方使用的接口,位于中轴线上的为双方都用到的接口. 图中从下至上分为十层,各层均为单向依赖,右 ...

  10. java多线程总结-同步容器与并发容器的对比与介绍

    1 容器集简单介绍 java.util包下面的容器集主要有两种,一种是Collection接口下面的List和Set,一种是Map, 大致结构如下: Collection List LinkedLis ...