码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2016-10-15 02:25:32      阅读:160      评论:0      收藏:0      [点我收藏+]

标签:

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

  我们要求出 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 }

 

 

    

 

 

 

  

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

标签:

原文地址:http://www.cnblogs.com/Parallels/p/5962600.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!