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

扩展欧几里得算法

时间:2015-05-14 23:50:21      阅读:177      评论:0      收藏:0      [点我收藏+]

标签:gcd   扩展欧几里得算法   

证明:设 a>b。
推理1,显然当 b=0,gcd(a,b)=a。此时 x=1,y=0;//推理1
推理2,a*b!=0 时
设 ax1+by1=gcd(a,b);
bx2+(a mod b)y2=gcd(b,a mod b);
根据朴素的欧几里德原理有 gcd(a,b)=gcd(b,a mod b);
则:ax1+by1=bx2+(a mod b)y2;
即:ax1+by1=bx2+(a-(a/b)*b)y2=ay2+bx2-(a/b)*by2;
根据恒等定理得:x1=y2; y1=x2-(a/b)*y2;//推理2
这样我们就得到了求解 x1,y1 的方法:x1,y1 的值基于 x2,y2.
上面的思想是以递归定义的,因为gcd不断的递归求解一定会有个时候b=0,
所以递归可以结束。

扩展欧几里得算法的通解与特解问题:
对于ax+by=gcd(a,b)来讲易由exgcd()求出其一组特解x0,y0
那么其通解的形式可以通过如下推导得出:设其另一组解为x1,y1
则有a*x1+b*y1=a*x0+b*y0,然后可以得到:a(x1-x0)=b(y0-y1)
两边同除gcd(a,b)设a/gcd(a,b)=a1,b/gcd(a,b)=b1, a1*(x1-x0)=b1*(y0-y1);
并a1,b1一定互素,必有(x1-x0)=k*b1,带入可得 a1*k=y0-y1,y1=y0-a1*k;
同理可将(y0-y1)=k*a1带入可得x1-x0=k*b1,x1=x0+k*b1;
然后对于更一般的方程ax+by=c;若c%gcd(a,b)!=0则无解,否则
通解为x=x0*k+t*b1;y=y0*k-t*a1(t为任意整数,推导过程与上式通解推导相同),特别注意:
下式的通解不等于上式通解扩大k倍!!!!!!!!
然后对于很多问题,求的并不是它的第一组解,而是满足一定要求的解
此时应该将x,y看成k的一次函数,然后进行相应的求解(比如由此法可以求x的最小整数解
只需通过令x=0,然后求出相应的t再回带就行

int exgcd(int a,int b,int& x,int &y) //扩展欧几里得算法,递归实现
{
if(b==0) //当b=0时递归结束是,得到一组解
{
x=1;
y=0;
return a; //返回的是a,b的最大公约数
}
int r=exgcd(b,a%b,x,y); //递归求解
int t=x; //求解结束后,由子问题得到父问题的解
x=y;
y=t-(a/b)*y;
return r;
}

void exgcd1(int a,int b,int &d,int &x,int &y)
{
if(b==0)
{
x=1;
y=0;
d=a; //d记录a,b的最大公约数
}
else
{
exgcd1(b,a%b,d,y,x);
y=y-x*(a/b);
}
}

#include<iostream>
int main()
{
   int x,y,d;
   cout<<exgcd(15,5,x,y)<<endl;
   cout<<"15x+5y=5的一组整数解为:"<<endl<<"x=:"<<x<<" y=:" <<y<<endl;
   getchar();getchar();
  return 0;
}

扩展欧几里得算法

标签:gcd   扩展欧几里得算法   

原文地址:http://blog.csdn.net/acm_lkl/article/details/45727827

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