欧几里得

本质:利用辗转相减法求最大公约数,即 gcd(a, b)。

数学表达: 设 a > b ,则

                         gcd(a, b) = gcd(a-b, b)

不断地利用大的数减去小的数,就能得到最大公约数。

证明:

设 a = k1 * g,  b = k2 * g,  g = gcd(a, b)

那么 gcd(k1, k2) = 1

设 a > b <=> k1 > k2 大数减小数

那么 a = (k1 - k2) * g,  b = k2 * g

我们可以发现a,b的变化为两个互质的系数在不断相减(始终还是互质),

g始终是它们的最大公约数,所以当有一个数变为0时,另一个不为0的数就是最大公约数。

代码如下:

int getgcd (int a, int b)
{if (a == 0)return b;else if (b == 0)return a;for (; a != b ;){if (a > b)a -= b;elseb -= a;}
}

---------------------------------------------------------------------------------------------------------------------------------

欧几里得优化(辗转相除)

我们发现当a一直大于b时,就会一直减去b,这其实就是变成 a mod b,于是我们可以利用辗转相除来优化。

代码如下:

int getgcd (int a,int b)
{return b == 0 ? a : getgcd(b, a % b);
}

---------------------------------------------------------------------------------------------------------------------------------

扩展欧几里得

扩展欧几里得的典型应用就是解决形如a*x + b*y = c 的二元一次方程的解的存在性问题和求出特解与通解。

解的存在性问题:

我们通过辗转相减可以观察出,a和b辗转相减的时候相当于 a*x + b*y 中的x和y在不断变化的过程,我们通过前面可以知道

这个过程一定能够得到最大公约数,所以 a*x + b*y = gcd(a, b) 方程一定有解。

那么是否 gcd(a, b) ?= c 的时候就无解呢?首先我们知道 c 是gcd(a, b) 的倍数才可能有解,因为左边一定含有因子 gcd(a, b)

左边等于右边,那么右边也一定含有 gcd(a, b),因此我们可以通过两边同时除以最大公约数得到一个新的式子:

k1*x + k2*y = c / g && gcd(k1, k2) = 1

由辗转相减可得: k1*x + k2*y = 1 一定有解,所以方程 k1*x + k2*y = c / g 一定有解

由此可得, a*x + b*y = c 中c是gcd(a, b)的倍数时,方程一定有解

特解与通解:

所以我们只需要求解形如

                         a*x + b*y = gcd(a, b)

的方程,然后将解扩大 c / gcd(a, b) 倍就可以解出原方程的解

辗转相减可得:

                         (a - b)*x1 + b*y1 = gcd(a, b)

变换一下可得:

                         a*x1 + b*(y1 - x1) = gcd(a, b)

联立原方程得: x = x1,  y = y1 - x1

我们可以不断将原问题变成一个规模更小的子问题,然后根据子问题的答案退出原问题的答案

又考虑可以用辗转相除优化,我们可以讲原问题变成求解:

                         b*x1 + a%b*y1 = gcd(a, b)

                         a%b = a - a/b * b

代入得

                         b*x1 + (a - a/b * b)*y1 = gcd(a, b)

得到

                         x = y1,  y = x1 - a/b * y1

因此我们只需一直缩小问题规模,知道变成 gcd(a, b)*x + 0*y = gcd(a, b),

得到一组特解 (1, 0),再讲其反推回去,得到原方程的一组特解。这个过程可以用一个递归函数来实现。

代码如下:

int getextcgd (int a, int b, int &x, int &y) // a*x + b*y = gcd (a,b)
{int d = a;if (b != 0){d = extgcd (b, a % b, x, y);x -= (a / b) * y;swap (x, y);}else{x = 1, y = 0;}return d;
}

函数执行完毕后x和y就是 a*x + b*y = gcd(a, b) 中的一组特解,

通解的变化规律就是 x 和 y 的值往相反的方向变化,比如 x 变大一些, y 变小一些,使得答案不变,

设这个变化的最小单位值为 d1, d2

                         a*(x + d1) + b*(y - d2) = gcd(a, b)

                         a * d1 = b * d2

两边同除 gcd(a, b) 令 k1 = a / gcd(a, b), k2 = b / gcd(a, b)

                         k1 * d1 = k2 * d2

这个时候k1,k2互质,显然 d1 = k2, d2 = k1,可得通解为

                         (x + k*d1, y - k*d2)

                         (x + k*b/gcd(a, b), y - k*a/gcd(a, b))

并且我们通过递归函数的实现可以观察到,解的绝对值是跟 a, b 的绝对值同一个级别的

【笔记】 欧几里得(扩展欧几里得)相关推荐

  1. 数论一之定理证明——裴蜀/威尔逊/费马/扩展欧几里得/[扩展]欧拉/[扩展]中国剩余定理,欧拉函数,逆元,剩余系,筛法

    打死没想到会在H老师处学懂数论 同余,整除 模运算 埃式筛法 欧拉筛法 最大公约数和最小公倍数 辗转相除法 更相减损术 裴蜀定理 威尔逊定理 费马定理 同余等价类.剩余系.缩系 欧拉函数 欧拉定理 扩 ...

  2. 欧几里得 扩展欧几里得

    欧几里得  &  扩展欧几里得 时间复杂度T(n):O(log2n); 空间复杂度S(n):O(n); Advantages: 1.    时间复杂度不高,和普通欧几里得一样: 2.    代 ...

  3. 【欧几里得扩展欧几里得】

    欧几里得 LL gcd(LL a,LL b){return (b==0) ? a : gcd(b,a%b);} 扩展欧几里得 int ex_gcd(int a,int b,int &x,int ...

  4. 欧几里得+扩展欧几里得+RSA

    欧几里得算法: 就是辗转相除法,gcd(a,b)=gcd(b,a%b), 实现简单,用途广泛,模板如下: int gcd(int a,int b)//或者都取 long long {return b! ...

  5. 欧拉降幂及其扩展欧拉降幂

    欧拉降幂: 从公式来看,需要使用快速幂运算和欧拉函数 #include<bits/stdc++.h>using namespace std; typedef __int64 LL;cons ...

  6. 欧几里得扩展欧几里得

    原博网址:http://www.cnblogs.com/frog112111/archive/2012/08/19/2646012.html 欧几里德算法 欧几里德算法又称辗转相除法,用于计算两个整数 ...

  7. 欧拉定理相关及扩展欧几里得

    威尔逊定理.费马定理.欧拉函数.欧拉定理.逆元.exgcd 威尔逊定理: ( p − 1 ) ! ≡ − 1 ( m o d p ) (p-1)! \equiv -1 \pmod p (p−1)!≡− ...

  8. 欧几里德 与 扩展欧几里得 学习笔记

    最近学了学扩展欧几里得,总结一下 欧几里得算法 欧几里得算法主要用来求a,b的最大公约数,又称为gcd 代码 int Gcd(int a,int b) {if(b==0) return a;else ...

  9. 欧几里得原理及扩展欧几里得原理(Euclidean Theory and Extended Euclidean Theory)学习笔记

    题记:这是我第四次复习扩展欧几里得原理,因为不常用到,想要使用的时候又想不起细节,总是要查资料,于是索性这次整理一下欧几里得原理及其扩展原理存档至博客以备查用. 一.欧几里得原理 欧几里得原理(Euc ...

最新文章

  1. Android深度探索与驱动开发(一)
  2. php7可以做什么开发,php7 图形用户界面GUI 开发怎么做?看完这个代码你就明白了...
  3. 使用Xshell连接Linux服务器
  4. 第二次冲刺每日站立会议04
  5. Runtime类及其常用方法
  6. DAZ studio 4.9基础
  7. php如何进行错误处理,php如何自定义错误处理
  8. python中意外缩进是什么意思_如何处理python中的“意外缩进”?
  9. leetcode 241 python
  10. nyoj 1321信息战(九)——水淹七军(搜索bfs)
  11. python量化回测框架_股票量化交易回测框架pyalgotrade源码阅读(一)
  12. 前端架构最全总结——GUI 应用程序架构的十年变迁:MVC、MVP、MVVM、Unidirectional、Clean...
  13. Chrome浏览器安装扩展程序后菜单栏图标不显示
  14. Matlab入门基础思维导图
  15. PPT太大如何压缩到最小?
  16. 22-Consent 确认逻辑实现
  17. pvs linux_Linux下用于C ++开发的PVS-Studio静态分析器入门
  18. on device trainning
  19. 手把手教你用Python打造一个语音合成系统(已生成软件)
  20. C语言使用fgetc()函数

热门文章

  1. 英特尔固态硬盘测试软件,AS SSD测试:IOPS值高达11万_Intel 520_固态硬盘评测-中关村在线...
  2. 2020中兴开发岗笔试题
  3. 【MySQL】MySQL的自然连接和USING连接详细总结
  4. 网络模型——四种常见网络IO模型
  5. 4.5/4.6 磁盘格式化 4.7/4.8 磁盘挂载 4.9 手动增加swap空间
  6. linux ps swn,Linux操作的基本概念与命令(转)
  7. java indexeddb_indexedDB 基本使用
  8. Bootstrap 组件 Button 按钮
  9. ARTS-9(幸福的奥秘是什么?)
  10. 多台显示器连接一台服务器,如何用一台显示器连接多台电脑?