扩展欧几里德算法及其应用

  接着欧几里德算法往后写,扩展欧几里德算法常常用来解不定方程及一些相关的应用,用到的思想就是欧几里德算法的思想:通过在结果不改变的情况下不断取余而逐步缩小数据规模,两个数会不断变小,直到减小到一个数是另一个数的倍数的时候,就很容易求出他们的最小公倍数了。下面我们来说说扩展欧几里德的思想:

  我们要求出 a * x + b * y = c 的所有解,其中 a,b,c 是已经告诉你的常数,而 x,y 是待求的未知量,我们要求出所有的 x,y ,其实只要求出一组 x0,y0就行了,剩下的解可以由 x=x0+k*(b*gcd(a,b)/a) , y=y0+k*(a*gcd(a,b)/b)求出,其中 k 为任意整数。

  而怎么求出一组 a * x + b * y = c 的解呢?首先判断是否有解的条件是 c%gcd(a,b) 是否等于 0。也就是说 c一定要是 a,b 的最大公约数的整数倍才有解,否则就没有整数解,这个只要自习想一想就可以理解,所以,我们只要求出  a * x + b * y =  gcd(a,b) 的一组解最后再乘以 c/gcd(a,b) 就好了。接下来我们说怎么求  a * x + b * y =  gcd(a,b)的解。

  到了重头戏,求 a * x + b * y =  gcd(a,b)的解,按照本文开头提到的想法,不断缩小数据规模,首先,在前面证明欧几里得算法的时候我们证明了 gcd(a,b)=gcd(a,a%b),现在我们提出另一个一个方程 b * x1 +a%b * y1 = gcd( b,a%b) ,这里的 a,b,x,y  还是上一个方程的 a,b,x,y ,但是可以看出,这个方程的系数比上一个方程小了,所以只要我们得到这个方程和原方程是解的关系,我们就可以利用这个方程化简数据规模,从而递归地求出方程的解。于是联立两个方程我们得到了 : x= y1; y=x1-a/b*y1;所以我们只要按照这个方法把x1,y1当成新的x,y再次递归下去就可以求出解。当然我们还要说一下递归的终止条件就是 有一个系数为0,这样就可以求出一组目前方程的确定的 x,y了(不是最终解),当然因为a始终大于b所以肯定是b先为0,这样就得到了退出递归的条件。最终得到的x,y就是a * x + b * y =  gcd(a,b)的一组解了。

  代码实现,C++,递归实现,这个是一开始写的,比较容易理解,但是常数大了一些:

 1 void Exgcd(int a,int b,int &x,int &y)
 2   {
 3       if(b==0)
 4      {
 5         x=1;
 6         y=0;
 7         return ;
 8     }
 9     Exgcd(b,a%b,x,y);
10     int t=x;
11     x=y;
12     y=t-a/b*y;
13     return ;
14  }

  后来在网上看到了另一种写法,这种写法比较好写,常数也小,推荐:

1 void Exgcd(int a,int b,int&x,int&y)
2 {
3      if(!b) { x=1,y=0;    return ;}
4      Exgcd(b,a%b,y,x);
5      y-=a/b*x;
6 }

  另外还有非递归的版本,因为写起来太麻烦,也没有递归版本效率高,所以就不写了-_-

  因为上面只是一个裸的函数,是在确定有解的情况下调用的(事实上不管有没有解调用函数后都会返回一组解),而且返回的解也不是最终解,所以我们还可以加一个判断函数来判断是否有解,并将返回的解转化为最终解:

 1 int gcd(int a,int b) {return b?  gcd(b,a%b):a;}
 2 bool check_exgcd(int a,int b,int c,int &x,int &y)
 3 {
 4     int k=gcd(a,b);
 5     if(c%k)
 6         return false;
 7     Exgcd(a,b,x,y);
 8     k=c/k;
 9     x*=k; y*=k;
10     return true;
11 }

  

  

时间: 2024-10-16 07:47:07

扩展欧几里德算法及其应用的相关文章

扩展欧几里德算法

文章来源:http://blog.csdn.net/zhjchengfeng5/article/details/7786595 谁是欧几里德?自己百度去 先介绍什么叫做欧几里德算法 有两个数 a b,现在,我们要求 a b 的最大公约数,怎么求?枚举他们的因子?不现实,当 a b 很大的时候,枚举显得那么的na?ve ,那怎么做? 欧几里德有个十分又用的定理: gcd(a, b) = gcd(b , a%b) ,这样,我们就可以在几乎是 log 的时间复杂度里求解出来 a 和 b 的最大公约数了

欧几里德与扩展欧几里德算法(转)

欧几里德算法 欧几里德算法又称辗转相除法,用于计算两个整数a,b的最大公约数. 基本算法:设a=qb+r,其中a,b,q,r都是整数,则gcd(a,b)=gcd(b,r),即gcd(a,b)=gcd(b,a%b). 第一种证明: a可以表示成a = kb + r,则r = a mod b 假设d是a,b的一个公约数,则有 d|a, d|b,而r = a - kb,因此d|r 因此d是(b,a mod b)的公约数 假设d 是(b,a mod b)的公约数,则 d | b , d |r ,但是a

HDU 1098 Ignatius's puzzle 费马小定理+扩展欧几里德算法

题目大意: 给定k,找到一个满足的a使任意的x都满足 f(x)=5*x^13+13*x^5+k*a*x 被65整除 推证: f(x) = (5*x^12 + 13 * x^4 + ak) * x 因为x可以任意取 那么不能总是满足 65|x 那么必须是 65 | (5*x^12 + 13 * x^4 + ak) 那么就是说 x^12 / 13 + x^4 / 5 + ak / 65 正好是一个整数 假设能找到满足的a , 那么将 ak / 65 分进x^12 / 13 + x^4 / 5中得到

欧几里德与扩展欧几里德算法

转自网上大牛博客,讲的浅显易懂. 原文地址:http://www.cnblogs.com/frog112111/archive/2012/08/19/2646012.html 欧几里德算法 欧几里德算法又称辗转相除法,用于计算两个整数a,b的最大公约数. 基本算法:设a=qb+r,其中a,b,q,r都是整数,则gcd(a,b)=gcd(b,r),即gcd(a,b)=gcd(b,a%b). 第一种证明: a可以表示成a = kb + r,则r = a mod b 假设d是a,b的一个公约数,则有

扩展欧几里德算法及其证明

扩展欧几里德算法: 已知a, b求解一组x,y,使它们满足等式: ax+by = gcd(a, b) =d(解一定存在,根据数论中的相关定理). 扩展欧几里德常用在求解模线性方程及方程组中. 证明: ax+by=gcd(a,b); 1. (1) a = 0,ax+by = gcd(a,b) = gcd(0,b) = b, 此时x = 0(此时x的值是任意的),y = 1: (2)b = 0, ax + by = gcd(a,b) = gcd(a,0) = a, 此时x = 1,y = 0(此时y

(扩展欧几里德算法)zzuoj 10402: C.机器人

10402: C.机器人 Description Dr. Kong 设计的机器人卡尔非常活泼,既能原地蹦,又能跳远.由于受软硬件设计所限,机器人卡尔只能定点跳远.若机器人站在(X,Y)位置,它可以原地蹦,但只可以在(X,Y),(X,-Y),(-X,Y),(-X,-Y),(Y,X),(Y,-X),(-Y,X),(-Y,-X)八个点跳来跳去. 现在,Dr. Kong想在机器人卡尔身上设计一个计数器,记录它蹦蹦跳跳的数字变化(S,T),即,路过的位置坐标值之和. 你能帮助Dr. Kong判断机器人能否

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

欧几里德算法 欧几里德算法又称辗转相除法,用于计算两个整数a,b的最大公约数. 基本算法:设a=qb+r,其中a,b,q,r都是整数,则gcd(a,b)=gcd(b,r),即gcd(a,b)=gcd(b,a%b). 第一种证明: a可以表示成a = kb + r,则r = a mod b 假设d是a,b的一个公约数,则有 d|a, d|b,而r = a - kb,因此d|r 因此d是(b,a mod b)的公约数 假设d 是(b,a mod b)的公约数,则 d | b , d |r ,但是a

HDU 1576 A/B 扩展欧几里德算法

A/B Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2017    Accepted Submission(s): 1469 Problem Description 要求(A/B)%9973,但由于A很大,我们只给出n(n=A%9973)(我们给定的A必能被B整除,且gcd(B,9973) = 1). Input 数据的第一行是一个

poj2142-The Balance(扩展欧几里德算法)

一,题意: 有两个类型的砝码,质量分别为a,b;现在要求称出质量为d的物品, 要用多少a砝码(x)和多少b砝码(y),使得(x+y)最小.(注意:砝码位置有左右之分). 二,思路: 1,砝码有左右位置之分,应对比两种情况 i,a左b右,得出方程 ax1 - by1 = d ; ii,b左a右,得出方程 bx2 - ay2 = d . 2,利用扩展欧几里德算法,解出(x1,y1).(x2,y2),并求出最小x1和x2,以及相对应的y1,y2. 3,输出x1+y1和x2+y2 中的最小值. 三,步骤

扩展欧几里德算法详解

扩展欧几里德算法 谁是欧几里德?自己百度去 先介绍什么叫做欧几里德算法 有两个数 a b,现在,我们要求 a b 的最大公约数,怎么求?枚举他们的因子?不现实,当 a b 很大的时候,枚举显得那么的na?ve ,那怎么做? 欧几里德有个十分又用的定理: gcd(a, b) = gcd(b , a%b) ,这样,我们就可以在几乎是 log 的时间复杂度里求解出来 a 和 b 的最大公约数了,这就是欧几里德算法,用 C++ 语言描述如下: 由于是用递归写的,所以看起来很简洁,也很好记忆.那么什么是扩