说明: 在不定方程之前,数集指的是正整数集; 全文以 (\%) 表示取模运算。
从更相减损术说起
可半者半之,不可半者,副置分母、子之数,以少减多,更相减损,求其等也。以等数约之。
最小公倍数定义为最大的 (a) ,使得 (a|b) 且 (a|c) 。记 (gcd(b,c)=a) 。
那么更相减损术就是说 (gcd(a,b)=gcd(a-b,b)) ( (a>b) ); (gcd(a,b)=a=b) ,并且迭代有限次数后,一定能得到 (a=b) 的情况。
感性理解
(a) 和 (b) 都是由长度为 (gcd(a,b)) 的块组成的。那么减一减一定还是 (gcd(a,b)) 长的块的整数倍。证明
(a) , (b) 相等情况证明略,操作步数有限性证明略。
设 (gcd(a,b)=k) ,那么 (a=a'k) , (b=b'k) 。由于 (a>b) ,所以 (a'>b') 。那么 (a - b=(a'-b')k eq 0) 。所以 (k|a-b) ,那么 (gcd(a-b,b)geqslant k) 。
而若 (gcd(a-b,b)>k) ,那么存在 (k'>1) ,使得 (kk'|b) 且 (kk'|a-b) 。那么 (k'|b) 且 (k'|a-b) 。那么 (k'|(a-b)+b) ,即 (k'|a) 。所以 (kk'|a) ,(kk'|b) 且 (kk'>k) 。这与 (gcd) 的最大性矛盾。所以 (gcd(a-b,b)leqslant gcd(a,b)) 。
综上所述, (gcd(a-b,b)=gcd(a,b)) 。
更快的实现:辗转相除法
当 (a) 远大于 (b) 的时候,更相减损术会花很多的时间让 (a) 不断地减去 (b) 。我们可以想办法加速这个过程——即用取余操作代替减法操作。
辗转相除法可以这样描述 :
假设 (ageqslant b) ,那么 (gcd(a,b)=gcd(b,a\%b)) , (b mid a) ; (gcd(a,b)=b) , (b|a) 。
而由于 (a\%b leqslant lfloorfrac{a}{2} floor) ,所以辗转相除法的时间复杂度是 (log) 级别的。
int Gcd(int a, int b)
{
if(a % b == 0) return a;
return Gcd(b, a % b);
}
int Gcd(int a, int b)
{
int m = a % b;
while (m)
{
a = b;
b = m;
m = a % b;
}
return b;
}
最大公约数的性质:裴蜀定理
裴蜀定理(或贝祖定理,Bézout's identity)得名于法国数学家艾蒂安·裴蜀。说明了对任何整数 (a) 、 (b) 和它们的最大公约数 (d) :若 (a) , (b) 是整数,且 (gcd(a,b)=k) ,那么对于任意的整数 (x) 和 (y) , (ax+by) 都一定是 (k) 的倍数;特别地,一定存在整数 (x) , (y) ,使 (ax+by=k) 成立。
证明:
设 (gcd(a,b)=k) ,所以 (k|a) 且 (k|b) 。由整除的性质,对于任意 (x,yin Z) , (k|ax+by) 。
设 (ax+by) 的最小正整数值为 (s) , (q = lfloorfrac{a}{s} floor) , (r=a \% s=a-q(ax+by)=a(1-qx)+b(-qy))。也就是说, (r) 也是 (ax+by) 的某个取值。而由于 (s) 的最小性,(r=0) 。即 (s|a) 。同样的,有 (s|b) 。又因为 (ax+by) 为 (k) 的倍数,所以 (s=k) 。
如何构造这样一组解?:扩展欧几里得算法
当 (b|a) 时, (gcd(a,b)=b) , (x=0,y=1) 是方程 (ax+by=b) 的一组解。
如果我们已经知道了 (x',y') 是方程 (bx+(a\%b)y=gcd(a,b)) 的一组解,那么有:[bx'+(a-blfloorfrac{a}{b} floor)y'=gcd(a,b)\ bx'+ay'-blfloorfrac{a}{b} floor y'=gcd(a,b)\ ay'+b(x'-lfloorfrac{a}{b} floor x')=gcd(a,b) ]即 (x=y') , (y=x'-lfloorfrac{a}{b} floor x') 就能得到 (ax+by=gcd(a,b)) 的一组解。
void exgcd(int a, int b, int &x, int &y, int &gcd)
{
if (b == 0)
{
x = 1;
y = 0;
gcd = a;
return;
}
exgcd(b, a % b, y, x, gcd);
y -= a / b * x;
return;
}
不定方程 (ax+by=c) 的最小整数解
通解形式
显然,如果 (gcd(a,b) mid c) ,方程无解。
先考虑方程 (ax+by=gcd(a,b)) 。为了让 (ax+by=gcd(a,b)) , (ax) 和 (by) 的值要同时变化 (lcm(a,b)) 。所以通解为
其中 (x') , (y') 是一组特解。
令 (p=frac{b}{gcd(a,b)}) 那么 (x=(x' \% p +p ) \%p) 就是 (x) 的最小正整数解。
然后在看方程 (ax+by=c) 。不难发现它的通解是
同样的,令 (p=frac{b}{gcd(a,b)}) 。为了防止溢出,可以这样算:
最后 (x) 可能为负数,所以 (x=(x+p)\%p) 即可。