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

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

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

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

  理解辗转相除,关键在于理解 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. 数据结构丨N叉树

    遍历 N叉树的遍历 树的遍历 一棵二叉树可以按照前序.中序.后序或者层序来进行遍历.在这些遍历方法中,前序遍历.后序遍历和层序遍历同样可以运用到N叉树中. 回顾 - 二叉树的遍历 前序遍历 - 首先访 ...

  2. ~~Py2&Py3~~

    进击のpython python2 整型 int -- long(长整型) /获取的是整数 python3 整型 int /获取的是浮点数(小数) python2 print(range(1,10)) ...

  3. Unity游戏神经网络版坦克大战

    基于遗传算法优化的神经网络来训练坦克AI是什么体验呢?下面有bulid好的demo. 包括window和安卓两个版本. 这是一个Unity项目. 下载链接:https://pan.baidu.com/ ...

  4. C4.5和ID3的差别

    C4.5和ID3的差别 决策树分为两大类:分类树和回归树,前者用于分类标签值,后者用于预测连续值,常用算法有ID3.C4.5.CART等. 信息熵 信息量:   信息熵: 信息增益 当计算出各个特征属 ...

  5. 详解svm和smo的出现

    SupportVector Machines are learning models used forclassification: which individuals in a population ...

  6. C#中Thread.IsBackground 属性

    Thread  thread.IsBackground =true; //Gets or sets a value indicating whether or not a thread is a ba ...

  7. RabbitMQ(三):RabbitMQ与Spring Boot简单整合

    RabbitMQ是目前非常热门的一款消息中间件,不管是互联网大厂还是中小企业都在大量使用.Spring Boot的兴起,极大地简化了Spring的开发,本文将使用Spring Boot与RabbitM ...

  8. flask+uwsgi+nginx+docker-compose部署

    简单介绍 Flask这里就不多阐述了,已经是很流行的一个轻量级python框架了,对于小.中型项目特别适合.这里用docker的compose编排部署.uwsgi 简单的说明下,uWSGI是一个Web ...

  9. SSM - Mybatis SQL映射文件

    MyBatis 真正的力量是在映射语句中.和对等功能的jdbc来比价,映射文件节省很多的代码量.MyBatis的构建就是聚焦于sql的. sql映射文件有如下几个顶级元素:(按顺序) cache配置给 ...

  10. IDEA自定义配置

    目录 1 常规设置 1 修改字体大小 2 创建文件时 增加注释信息 3 项目编码为UTF-8 4 properties 文件编码为UTF-8且Transparent native-to-ascii c ...