- 扩展欧几里得模板。
- 求解两个元是整数的方程可以转换为取余消元枚举其中一个数,这是另一种思路。
- 复杂度和gcd一样是lg(n)。
- gcd(a,b)//a,b可以是任意整数,但是为了保证结果是正的,所以让a,b取绝对值. 显然gcd(a,b) == gcd(|a|,|b|)
long long e_gcd(long long a, long long b, long long& x, long long& y){
if(b == 0){
x = 1;
y = 0;
return a;
}
long long ans = e_gcd(b, a%b, y, x);
y -= x*(a/b);
return ans;
}
推导思路:
当最底层时,gcd(a,0)==a==a*1+b*0;
又因为公因数相等,所以可以找到上一步的一个式子联立,找到递推关系.
应用:
1.求解不定方程。
2.求解模的逆元。
3.求解同余方程。
以上三个换汤不换药。
设: ax+by=c
当且仅当c%gcd(a,b) == 0时才有整数解。
x,y可能为负数。
通解:
X = x + b/gcd(a,b)*t //t可以是负数
Y = y - a/gcd(a,b)*t //利用最小公倍数保证求出的解时最小的。
最小解:令 m = | b/gcd(a,b) |;
( (x % m) + m) % m;//保证结果是正数
也可以当x为负的时候再加一个m来保证结果是正数。
如果c != gcd(a,b), 那么先利用e_gcd函数得到原方程的特解:x0*c/gcd(a,b),再通过( (x % m) + m) % m得到最小正整数解。
为什么要先得到特解再找最小正整数解?
令m == b/ gcd(a,b)
n == a/ gcd(a,b)
显然am == bn
假设c/gcd(a,b) == 2:
如果不是先得到特解,而是先找最小正整数解最后再乘以2,
则:
2*x0*a + 2*y0*b = c
当x0增加m时:
2*x0*a+2ma + 2*y0*b-2bn = c
此时我们就发现2*x0*a+ma + 2*y0*b-bn = c这个式子也成立,但是永远都取不到了。
如果先取特解再找最小正整数解,则每次变动单位为ma都可以取得到。