扩展欧几里得算法模板

对于整数a,b,x,y,c

有a*x+b*y=c,如果c不是a与b的最大公约数的倍数,那么此方程无解

证明:设gcd(a,b)=d,即最大公约数,那么a*x%d=0,b*y%d=0

则(a*x+b*y)%d=0,说明c是一个d的倍数,相反的,如果c不是d的倍数,那么次方程无解

对于欧几里得算法 int extend_eulid(int a,int b,int &x,int &y)

返回值是a,b的最大公约数,求解的x和y满足a*x+b*y=d的一个解

那么如何求a*x+b*y=c的解呢?假设x0,y0,是通过欧几里得算出来的一个解,即a*x0+b*y0=d,因为c%d=0

因此:a*x0*(c/d)+b*y0*(c/d)=d*(c/d)转化为  a*(x0*(c/d))+b*(y0*(c/d))=c

所以算出a*x+b*y=c的解  x=x0*(c/d), y=y0*(c/d)。

令r=fabs(b/d);//保证为正数

minx = (x%r+r)%r为最小非负解(这一点没想明白)

 

因为gcd(a,b)=gcd(b,a%b)=d

a*x+b*y=d,b*x0+(a%b)y0=d

所以a*x+b*y=b*x0+(a%b)y0

    =b*x0+(a-a/b*b)y0

    =a*y0+b*(x0-a/b*y0)

因此x=y0, y = x0 – a / b * y0;

由此可得到递归程序:

 1 #include <iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 
 6 int extend_euclid(int a,int b,int &x,int &y)
 7 {
 8     //b等于0时递归结束,得到该步的解,通过该解返回到上一步的出上一步的解
 9     if(b==0)
10     {
11         x=1;
12         y=0;
13         return a;
14     }
15     int d = extend_euclid(b,a%b,x,y);
16     int t = x;
17     x=y;
18     y=t-a/b*y;
19     return d;//a,b的最大公约数
20 }
21 int main()
22 {
23     int x,y;
24     printf("%d\n",extend_euclid(9,15,x,y));
25     printf("%d% d\n",x,y);
26     return 0;
27 }

 

posted on 2016-08-09 22:10  wastonl  阅读(256)  评论(0编辑  收藏  举报