欧几里得算法 以及 扩展
欧几里得算法
int gcd(int a, int b)
{
return b==0?a:gcd(b,a%b);
// whlie (b^=a^=b^=a%=b); return a;
}
证明:
如果 \(x|a\) 且 \(x|b\),则 \(a = mx, b = nx\)。所以 \(a - b = mx - nx = (m - n)x\),即 \(x|a-b\)。
相反,如果 \(x|a-b\) 且 \(x|b\),则 \(a-b = mx, b = nx\)。所以 \(a - b + b = mx + nx = (m + n)x\),即 \(x|a\)。
若 \(x\) 为 \(a\) 与 \(b\) 的公因数,那么我们证明了 \((a,b)\) 与 \((a-b,b)\) 的公因数相同。
因为 \((a,b)\) 与 \((a-b,b)\) 的公因数相同,\((a-b,b)\) 与 \((a-b-b,a-b)\) 的公因数相同,所以 \((a-k\times b,b)\) 与 \((a,b)\) 的公因数相同,即 \((a\mod b,b)\) 与 \((a,b)\) 的公因数相同。
因为 \(\gcd(a,0)=a\),所以我们有了边界条件。
其他:
(1)由唯一分解定理,可知 \(a\times b = gcd(a,b)\times lcm(a,b),\ \ \ lcm(a,b)=a/gcd(a,b)\times b\)。
(2)由于 辗转相除法 与 斐波那契数列 的性质,对两个大的相邻的斐波那契数求最大公倍数是较慢的。(优化辗转相除法)
gcd(a,b) ans=1
1、a,b除以2,直到为奇数为止,记录a,b除以2的次数中较小的那个,记为x。ans*=2^x
;
2、新得到的a,b用欧几理德算法。但是每次得到的a%b都要除以2直到为奇数。
3、ans*=b
;
扩展欧几里得算法
int exgcd(int a, int b, int &x, int &y)
{
if (b == 0)
{
x = 1, y = 0;
return a;
}
int r = exgcd(b, a%b, y, x);
y -= a/b*x;
return r;
}
证明:
由 裴蜀定理 可知,\(ax + by = \gcd(a,b)\),所以当且仅当 \(c\) 是 \(\gcd(a,b)\) 的倍数时,该不定方程才有解。
设:\(a>b\)
则有 \(\gcd(a,b)=\gcd(b,a\bmod b)\)
又因为 \(ax_1+by_1=\gcd(a,b),\ bx_2+(a\bmod b)y_2=\gcd(b,a\bmod b)\) 可得
由 恒等定理 可得:\(x_1=y_2,\ y1 = x_2-\left\lfloor\dfrac{a}{b}\right\rfloor y_2\)。
特别的,当 \(b = 0\) 时 \(x = 1, y = 0\)。
应用:
(1)解不定方程 \(ax+by=c\),则 \(x,y\) 为原方程的一组解,且 \(|x|+|y|\) 的值最小。
其他的解为 \(x+m*b,y-m*a,m\in\Z\)。
int BDFC(int a, int b, int c, int &x, int &y)
{
int d = exgcd(a, b, x, y);
if (c%d) return -1;
int k = c/d;
x *= k, y *= k;
}
(2)求解线性同余方程(同余方程也可以写为不定方程的形式)。
(3)求模意义下的逆元。