再探最大公约数
说明: 在不定方程之前,数集指的是正整数集; 全文以 \(\%\) 表示取模运算。
从更相减损术说起
可半者半之,不可半者,副置分母、子之数,以少减多,更相减损,求其等也。以等数约之。
最小公倍数定义为最大的 \(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\neq 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\) 。我们可以想办法加速这个过程——即用取余操作代替减法操作。
辗转相除法可以这样描述 :
假设 \(a\geqslant b\) ,那么 \(\gcd(a,b)=\gcd(b,a\%b)\) , \(b\nmid a\) ; \(\gcd(a,b)=b\) , \(b|a\) 。
而由于 \(a\%b \leqslant \lfloor\frac{a}{2}\rfloor\) ,所以辗转相除法的时间复杂度是 \(\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,y\in Z\) , \(k|ax+by\) 。
设 \(ax+by\) 的最小正整数值为 \(s\) , \(q = \lfloor\frac{a}{s}\rfloor\) , \(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-b\lfloor\frac{a}{b}\rfloor)y'=\gcd(a,b)\\ bx'+ay'-b\lfloor\frac{a}{b}\rfloor y'=\gcd(a,b)\\ ay'+b(x'-\lfloor\frac{a}{b}\rfloor x')=\gcd(a,b) \]即 \(x=y'\) , \(y=x'-\lfloor\frac{a}{b}\rfloor 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) \nmid 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\) 即可。