最大公约数(Greatest Common Divisor)

欧几里得算法:

定理1:设a,b,c,q都为整数,且b>0。如果 a = q b+c,那么 gcd(a, b) = gcd(b, c)

证明方法用了集合的方法,就是说明一个的约数必定是另一个数的约数,从而两个数相等。

用这个定理就可以写出欧几里得算法

(1)迭代版本

int ITERATIVE-GCD(int a, int b) { int r = a % b; while (r) { a = b; b = r; r = a % b; } return b; }

(2)递归版本

int RECURSIVE-GCD(int a, int b) { if (b == 0) return a; else return RECURSIVE-GCD(b, a % b); }

显然,递归的比迭代的写起来方便,不容易错,但是效率是否会差很多呢?

定理2:(由法国数学家拉梅证明)欧几里得算法所需除法次数不超过m和n中较小的那个数的十进制位数的5倍

定理3:(稍弱点)……不超过2 log(n+1),其中n为较小的数

有了上面的定理,有理由相信递归版本的优势,但学的时候两种都要会!

拓展的欧几里得算法(Extended Euclidean Algorithm)

可以用来求二元一次方程组的整数解问题

ax + by = m,要求gcd(a, b) = 1,否则两边同除以GCD,最后结果再乘以GCD

(3)迭代的拓展欧几里得算法

#include <stdio.h> int extended_euclidean(int n, int m, int &x, int &y) { int x1 = 1, x2 = 0, x3 = n; int y1 = 0, y2 = 1, y3 = m; while (x3 % y3 != 0) { int d = n / m; int t1, t2, t3; t1 = x1 - d * y1; t2 = x2 - d * y2; t3 = x3 - d * y3; x1 = y1; x2 = y2; x3 = y3; y1 = t1; y2 = t2; y3 = t3; }; x = y1; y = y2; return y3; } int main() { int n, m; while (scanf("%d%d", &n, &m) == 2) { int x, y, gcd; gcd = extended_euclidean(n, m, x, y); printf("The GCD of %d and %d is %d ./n %d * %d + %d * %d = 1/n", n, m, gcd, n, x, m, y); } return 0; }

(4)递归的拓展欧几里得算法

int extended_euclidean(int n, int m, int &x, int &y) { if (m == 0) { x = 1; y = 0; return n; } int g = extended_euclidean(m, n % m, x, y); int t = x - n / m * y; x = y; y = t; return g; }

递归的容易写,容易记。

知道了一个解,该方程的所有整数解都可以表示出来

x = x0 + b k

y = y0 + a k

这样,如果要求最小的正整数解也就可以算出来了!

原理:摘自网上

令a1=a/gcd(a,b),b1=b/gcd(a,b),m1=m/gcd(a,b)。如果我们能够首先求出满足a*x1+b*y1=gcd(a,b)这个方程的x1和y1,那么x=x1*m1,y=y1*m1就可以求出来了。由欧几里德算法gcd(a,b)=gcd(b,a%b),所以a*x1+b*y1=gcd(a,b)=gcd(b,a%b)=b*x2+(a%b)*y2,现在只要做一些变形就可以得到扩展欧几里德算法中的用到的式子了。令k=a/b(商),r=a%b(余数),那么a=k*b+r。所以r=a-k*b,带入上式,得到a*x1+b*y1=b*x2+(a-(a/b)*b)y2=a*y2+b*(x2-(a/b)*y2) => x1=y2,y1=x2-(a/b)*y2。有了这两个式子我们就知道了在用欧几里德求最大公约数的时候,相应的参数x,y的变化。现在再回过头来看一下扩展欧几里德算法的代码就很好理解了,实际上扩展欧几里德就是在求a和b的最大公约数的同时,也将满足方程a*x1+b*y1=gcd(a,b)的一组x1和y1的值求了出来。下面代码中突出的部分就是标准的欧几里德算法的代码。

应用:

(1)求数对于某个质数的逆元

extended_euclidean(n, p, x, y); x = x % p; if (x < 0) x += p;//由于 x 有可能是负数,故还要对 p 取模

(2)  USACO 4.1 nuggets 正整数解的存在问题

ax+by=c, where gcd(a,b)=1, a>0, b>0;  a posivesolution exists if c>=a*b
 PROOF:
from Extended Euclidean, we know that there exists a solution ax0+by0=c
**   we want to find xn, yn, where xn>0, yn>0. xn = x0 + b*t, yn = y0 - a*t;
**   -x0/b <= t <= y0/a。for c >= a*b, we know that x0/b+y0/a>=1, so it exists

(3)FZU APRIL 排列

/********************************* ** Description: C(N,M)%P (1 <= N <= 10E9, 1 <= M <= 10E4, 1 <= P <= 10E9) ** Algorithm: EXTENDED_EUCLIDEAN ** Analysis: 由于M比较小,所以可以用原始的定义求;但涉及逆元的求法! ** Time: 2011-04-17 18:43:08 **********************************/ #include <stdio.h> long long exgcd(long long n, long long m, long long &x, long long &y) { if (m == 0) { x = 1; y = 0; return n; } long long g = exgcd(m, n % m, x, y); long long t = x - n / m * y; x = y; y = t; return g; } int main() { long long n, m, p, cases; scanf("%I64d", &cases); while (cases--) { scanf("%I64d%I64d%I64d", &n, &m, &p); long long x, y, ans = 1, i, j; for (i = n, j = m; j >= 1; i--, j--) { exgcd(j, p, x, y); x = x % p; if (x < 0) x += p; ans = (ans*i)%p; ans = (ans*x)%p; } printf("%I64d/n", ans); } }

注意中间结果可能会超过INT,故用要LONG LONG

欧几里得、扩展的欧几里得算法相关推荐

  1. 欧几里得  拓展欧几里得算法 讲解 (Euclid Extend- Euclid Algorithm)

    欧几里得& 拓展欧几里得(Euclid & Extend-Euclid) 欧几里得算法(Euclid) 背景: 欧几里德算法又称辗转相除法,用于计算两个正整数a,b的最大公约数.   ...

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

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

  3. Java实现算法导论中求解模线性方程解(基于最大公约数欧几里得扩展算法)

    基于最大公约数欧几里得扩展算法求解算法导论中模线性方程解.具体要结合算法导论中的有关数论算法章节理解,具体代码如下: package cn.ansj;/*假设方程ax=b(mod n)有解,且x0是方 ...

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

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

  5. 欧几里得及欧几里得扩展算法

    (1)欧几里得算法 defination:if x and y are positive and x >= y,then gcd(x,y) = gcd(x mod y,y). 又叫辗转相除法,用 ...

  6. 欧几里得扩展欧几里得算法及相关的数学证明

    //欧几里得算法求最大公约数 int gcd(int m,int n) {int u0=m,u1=n,t;if( u0<u1 )// 保证u0>=u1u0^=u1,u1^=u0,u0^=u ...

  7. 欧几里得扩展欧几里得算法

    #朴素的欧几里得算法大家应该知道 g c d ( a , b ) gcd(a,b) gcd(a,b)表示a,b的最大公约数 朴素的欧几里得算法其实就是所谓的辗转相除法 辗转相除法 g c d ( a ...

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

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

  9. 欧几里得扩展欧几里得

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

最新文章

  1. 大脑是怎样和身体交流的?
  2. Silverlight 和WPF的Composite Guidance(Prism V2)发布了
  3. Java中New一个对象是个怎么样的过程?
  4. python3断言_Python3断言
  5. 坑 之 tensorflow使用sess.run处理图片时越来越慢,占用内存越来越大的问题
  6. redis内存行数据库细节
  7. 通过流进行字符集编码转换
  8. 《Windows驱动开发技术详解》之HelloDDK
  9. android vitamio 教程,使用vitamio开发步骤
  10. express基本原理
  11. pycharm不认识numpy?_深度学习(CV方向)入坑不完全指南
  12. DevOps使用教程 华为云(17)git 比较2个分支版本的差异 某个具体文件的差异
  13. 产品经理面试问题及答案大全《一》
  14. 2019年架构软考论文押题(一)
  15. 【webrtc】基于libyuv的转换
  16. 机器学习之ROC曲线绘制
  17. continous attractor neural networks - 连续吸引子网络(ing)
  18. 提供免费的Java OA系统 解决方案
  19. 杨韬的Python/Jupyter学习笔记
  20. 如何在电脑上用Win11便签备忘录提醒重要工作

热门文章

  1. docker部署seaweedf
  2. GateData Graph Digitizrer 图片中原始曲线数据提取——科研利器
  3. dnf加物理攻击的卡片有哪些_dnf物理攻击宝珠_dnf2019物理攻击宝珠大全_快吧游戏...
  4. 删除MySQL表的SQL语句-DROP-TABLE-简介
  5. (一)protege之使用入门
  6. github / gist
  7. 临时或永久修改cgroup和Cgroup 入门教程:cpuset
  8. 四平方和定理 leetcode279 c++
  9. HTML文件不小心删了怎么办,如何找回电脑被删除的文件
  10. sql增删改查语句实例