拓展欧几里得算法
定义
对于不定方程 \(ax+by=c\) , \(d=gcd(a,b)\) 的求解中,人们发现当仅 \(d|c\),即 \(gcd(a,b)\) 为 \(c\) 的因子时可得一组整数解 \((x,y)\).为求出使得 \(ax+by=d\) 的解,通常采用拓展欧几里得算法.
狭义的欧几里得算法即求 \(\text{gcd(a,b)}\) ,而广义的欧几里得算法希望进一步求出使得 \(ax+by=d=\text{gcd(a,b})\) 的 \((x,y)\).
拓展欧几里得算法
\[\begin{cases}
ax+by=d=gcd(a,b)\\
bx_1+(a\mod b)y_1=gcd(b,a\mod b)\\
gcd(a,b)=gcd(b,a\mod b)\\
a\mod b=a-kb
\end{cases}\]
则整理:
\[ax+by=bx_1+(a-kb)y_1=ay_1+b(x_1-ky_1)
\]
\[\Rightarrow
\begin{cases}
x=y1\\
y=x1-ky_1
\end{cases}\]
- 当 \(b=0\) 时,显然 \(gcd(a,b)=a\),此时 \(x=1,y=0\)
- 若 \(b\neq 0\) 时,则向下递归得 \(\text{Exgcd(b,a-kb)}\) 的解 \((x_1,y_1)\) ,并使 \((x,y)\leftarrow(y_1,x_1-ky_1)\)
其他(待补)
- 迭代法
- 矩阵法
代码
欧几里得
int gcd(int a,int b){
if(a<b)swap(a,b);
return b==0?a:gcd(b,a%b);
}
拓展欧几里得
int gcd(int a, int b, int& x, int& y) {
x = 1, y = 0;
int x1 = 0, y1 = 1, a1 = a, b1 = b;
while (b1) {
int q = a1 / b1;
tie(x, x1) = make_tuple(x1, x - q * x1);
tie(y, y1) = make_tuple(y1, y - q * y1);
tie(a1, b1) = make_tuple(b1, a1 - q * b1);
}
return a1;
}
迭代
int gcd(int a, int b, int& x, int& y) {
x = 1, y = 0;
int x1 = 0, y1 = 1, a1 = a, b1 = b;
while (b1) {
int q = a1 / b1;
tie(x, x1) = make_tuple(x1, x - q * x1);
tie(y, y1) = make_tuple(y1, y - q * y1);
tie(a1, b1) = make_tuple(b1, a1 - q * b1);
}
return a1;
}
矩阵
int exgcd(int a, int b, int &x, int &y) {
int x1 = 1, x2 = 0, x3 = 0, x4 = 1;
while (b != 0) {
int c = a / b;
std::tie(x1, x2, x3, x4, a, b) =
std::make_tuple(x3, x4, x1 - x3 * c, x2 - x4 * c, b, a - b * c);
}
x = x1, y = x2;
return a;
}