扩展欧几里得

来源:互联网 发布:淘宝指数怎么用 编辑:程序博客网 时间:2024/05/19 13:20

实际上扩展欧几里德就是在求a和b的最大公约数的同时,也将满足方程a*x1+b*y1=gcd(a,b)的一组x1和y1的值求了出来。下面代码中突出的部分就是标准的欧几里德算法的代码。

__int64 exGcd(__int64 a,__int64 b,__int64 &x,__int64 &y){
if(b==0){
x=1;
y=0;
return a;
}
__int64 g=exGcd(b,a%b,x,y);
__int64 temp=x;
x=y;
y=temp-(a/b)*y;
return g;
}

2.那么x,y的一组解就是x1*m1,y1*m1,但是由于满足方程的解无穷多个,在实际的解题中一般都会去求解x或是y的最小正数的值。以求x为例,又该如何求解呢?还是从方程入手,现在的x,y已经满足a*x+b*y=m,那么a*(x+n*b)+b*(y-n*a)=m显然也是成立的。可以得出x+n*b(n=…,-2,-1,0,1,2,…)就是方程的所有x解的集合,由于每一个x都肯定有一个y和其对应,所以在求解x的时候可以不考虑y的取值。取k使得x+k*b>0,x的最小正数值就应该是(x+k*b)%b,但是这个值真的是最小的吗??如果我们将方程最有两边同时除以gcd(a,b),则方程变为a1*x+b1*y=m1,同上面的分析可知,此时的最小值应该为(x+k*b1)%b1,由于b1<=b,所以这个值一定会小于等于之前的值。在实际的求解过程中一般都是用while(x<0)x+=b1来使得为正的条件满足,为了更快的退出循环,可以将b1改为b(b是b1的倍数),并将b乘以一个倍数后再加到x上。

PS:在求x的最小正数的时候采用while(x<0)x+=b在时间上有的时候是很不理想的,有其实x,b都很小的情况下。
实际上只要用通过x=(x%b1+b1)%b1就可以了,因为负数取余相当于正数取余再加个负号