扩展欧几里德算法是用来在已知a, b求解一组p,q使得p * a+q * b = Gcd(p, q) (解一定存在,根据数论中的相关定理)。
扩展欧几里德常用在求解模线性方程及方程组中。
下面是一个使用C++的实现:(拓展欧几里得算法的时间复杂度跟gcd()欧几里得算法复杂度是一样的)
int extended_gcd(int a, int b, int &x, int &y)
{
int ret, tmp;
if (!b)
{
x = 1; y = 0; return a;
}
ret = extended_gcd(b, a % b, x, y);
tmp = x;
x = y;
y = tmp - a / b * y;
return ret;
}
以下这一小段蓝色的只是证明过程,看不太懂的可以过……记住公式,懂得如何用就行。
把这个实现和Gcd的递归实现相比,发现多了下面的x,y赋值过程,这就是扩展欧几里德算法的精髓。
可以这样思考:
对于a' = b, b' = a % b 而言,我们求得 x, y使得 a'x + b'y = Gcd(a', b')
由于b' = a % b = a - a / b * b (注:这里的/是程序设计语言中的除法)
那么可以得到:
a'x + b'y = Gcd(a', b') ===>
bx + (a - a / b * b)y = Gcd(a', b') = Gcd(a, b) ===>
ay +b(x - a / b*y) = Gcd(a, b)
因此对于a和b而言,他们的相对应的p,q分别是 y和(x-a/b*y)
重点:关于使用扩展欧几里德算法解决不定方程的办法
对于不定整数方程ax+by=c;
判断是否有解:
若 c mod Gcd(a, b)=0,则该方程存在整数解,否则不存在整数解。
解不定方程ax+by=c;
解这个不定方程可以用扩展欧几里德算法。
对于不定方程ax+by=c的通解为:
x=x0*c/d+b/d*t
y=y0*c/d+a/d*t
当c%gcd(a,b)!=0时,不定方程无解.
剩下需要做的就是用x=x0*c/d+b/d*t
求出一个最小的正整数x,
得到的x0,y0有可能是负值,(如果你要求x0,y0的最小正值)这个时候,就需要用到上面的两条式子来求,用while来判断所得的x是否大于0就可以了。
上个用来求二元不定方程的extended gcd模板:
#include
using namespace std;
int extended_gcd(int a, int b, int &x, int &y)
{
int ret, tmp;
if (!b)
{
x = 1; y = 0; return a;
}
ret = extended_gcd(b, a % b, x, y);
tmp = x;
x = y;
y = tmp - a / b * y;
return ret;
}
int main()
{
int a,b,x,y,cas;
scanf("%d",&cas);
while(cas--)
{
scanf("%d%d",&a,&b);
int gc=extended_gcd(a,b,x,y);//这里的x,y在函数中是最为被引用的参数,所以函数结束,x,y的值就改变了,就是x0,y0
}
return 0;
}