扩展欧几里得算法

ax + by = gcd(a,b) 

若a≠0,b≠0,gcd(a,b)是ax+by的线性组合的最小正元素。

证明:

  1. 设gcd(a,b) = d。
  2. gcd(b,a mod b) = d'\Rightarrowbx' + (a mod b)y' = d'\Rightarrow令a / b = k(向下取整),则d' = bx' + (a - kb)y' = ay' + b(x'-ky')。
  3. gcd(a,b) = gcd(b,a mod b)\Rightarrowd = d'\Rightarrowax + by = ay' + b(x'-ky')。
  4. x = y',y = x'-ky'。
  5. b = 0\Rightarrowa*1+b*0 = d = a。

ax+by = c

  1. 求出gcd(a,b),如果gcd可以整除c那么存在解;否则无解。
  2. 求出ax + by = gcd(a,b)的一组解(x*,y*),那么ax + by = c 的一个组解为(x*c/d,y*c/d)。
  3. ax1 + by1 = ax2 + by2\Rightarrowa(x1 - x2) = b(y2 - y1),令d = gcd(a,b),两边同时除以d,得a'(x1 - x2) = b'(y2 - y1)\Rightarrow                (x1 - x2) = b'(y2 - y1)/a'。因为x1 - x2是b'的倍数,所以令x1 - x2 = kb',代入消去得y2 - y1 = ka'。
  4. 所以通解表达式(x*+kb',y*-ka')
  5. 最小整数解为:x = (x%b+b)%b。注意:对应的y不是(y%a+a)%a。

ax\equivb(mod n)

  1. 转化为ax + ny = b的形式求解。
  2. gcd(a,n) = 1,有唯一解。所以当b = 1,x即为乘法逆元,且必定存在。

代码:

​
void extgcd(int a,int b,int &d,int &x,int &y){
    if(!b){d = a; x = 1,y = 0;}
    else {extgcd(b,a%b,d,y,x); y -=x*(a/b);}   //这里y和x交换很巧妙,看着公式理解
}
void solve(){
	extgcd(a,b,d,x,y);
	if(c % d)	printf("Impossible\n");
	else{
		a /= d,	b /= d,	c /= d;
		x *= c,	y *= c;
		for(int k=-2;k<=2;k++)	printf("(%d %d)\n",x+k*b,y-k*a)
	}
}

 

posted @ 2020-05-16 10:42  月光下の魔术师  阅读(6)  评论(0)    收藏  举报