ax + by = gcd(a,b)
若a≠0,b≠0,gcd(a,b)是ax+by的线性组合的最小正元素。
证明:
- 设gcd(a,b) = d。
- gcd(b,a mod b) = d'
bx' + (a mod b)y' = d'
令a / b = k(向下取整),则d' = bx' + (a - kb)y' = ay' + b(x'-ky')。
- gcd(a,b) = gcd(b,a mod b)
d = d'
ax + by = ay' + b(x'-ky')。
- x = y',y = x'-ky'。
- b = 0
a*1+b*0 = d = a。
ax+by = c
- 求出gcd(a,b),如果gcd可以整除c那么存在解;否则无解。
- 求出ax + by = gcd(a,b)的一组解(x*,y*),那么ax + by = c 的一个组解为(x*c/d,y*c/d)。
- ax1 + by1 = ax2 + by2
a(x1 - x2) = b(y2 - y1),令d = gcd(a,b),两边同时除以d,得a'(x1 - x2) = b'(y2 - y1)
(x1 - x2) = b'(y2 - y1)/a'。因为x1 - x2是b'的倍数,所以令x1 - x2 = kb',代入消去得y2 - y1 = ka'。
- 所以通解表达式(x*+kb',y*-ka')
- 最小整数解为:x = (x%b+b)%b。注意:对应的y不是(y%a+a)%a。
ax
b(mod n)
- 转化为ax + ny = b的形式求解。
- 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)
}
}