窝们可以先来看一个式子:

\[ax + by = gc d(a,b) \]

根据欧几里得可以得到:

\[gcd(a,b) = gcd(b, a \% b) \]

不会欧几里得的同学们可以看这里

又根据原式可以推出 :

\[gcd(b, a \% b) = b * x_1 + (a \% b) * y_1 \]

所以可以得到:

\[a * x + b * y = b * x_1 + (a \% b) * y_1 \]

再化简,得:

\[x * a + y * b = x_1 * b + (a - (\frac{a}{b}) * b) * y_1 \]

运用主元法,可得:

\[x * a + y * b = y_1 * a + (x_1 - \frac{a}{b} * y_1) * b \]

窝们把 \(a, b\) 当作元,再来重新来看这个问题。

对于一个丢番图方程,\(a * x + b * y = a_1 * x_1 + b_2 * y_1\)

是不是肯定会有这样一组解:\(a = a_1\)\(b = b_2\)

那么原方程是不是肯定会有一个这样的根:

\[x = y_1 \\ y = x_1 - \frac{a}{b} * y_1 \]

如果你可以理解上面这些步骤,那么你肯定可以知道这个 \(x, y\) 是可以递归求解的。只不过要处理一下 \(-\frac{a}{b} * y_1\)

那么,窝们先来看看代码怎么实现,说不定看完你就懂了。

void exgcd(int a, int b, int &x, int &y) {
    if(b == 0) {x = 1, y = 0; return a;}//这个是一个必然存在的解,后面解释。
    exgcd(b, a % b, y, x);//这是不断递归,窝们前面对于y的变换法则中,窝们只管了x1,后面那个式子先不管他,至于前面这个a,b为什么要这样递归,是因为窝们转换原方程的时候是借助了欧几里得,所以窝们这个式子递归的时候也需要改变a,b。让a1,b1变成b,a % b;
    y -= (a / b) * x;//这里再来处理y转移的时候后面的那一部分。直接在递归的过程中去减去就行了,由于减完后这一层就直接结束了,所以不会影响其他 % 运算……运算的结果。
}

这里再来解释一下为什么 \(b == 0\) 的时候,原方程必有根。

如果 \(b == 0\) :

那么原式就可以化成这个样子:

\[a * x + 0 * y = gcd(a, 0) = a \]

那么这个式子中,如果 \(x == 1\) 肯定会有 :

\[x + 0 = x \ \ 原方程成立 \]

此时, \(y\) 可以取任意值,所以在那个里面的 \(y\) 不一定要赋值为 \(0\)\(1\), \(2\), \(3\)都可以,不过赋值为 \(0\) 是最小的。

既然已经知道了\(b == 0\) 的时候必然有解,又可以理解前面的方程转化的过程,那么恭喜你,你证完扩展欧几里得辣!!!

你太巨辣!!!