已经求出一组整数 x,y 使得 ax + by = 1,也就是 \frac{1-ax}{b} = y。y 是整数,可见目前 1-ax 是 b 的倍数。
现在想改变 x 并使得方程仍然成立。已知 a,b 互质,假若 x 的变化量(\Delta x)不是 b 的倍数,则 1-ax 的变化量(-a×\Delta x)也不是 b 的倍数,这会使得 1-ax 不再是 b 的倍数,则 y 不是整数了。
仅当 x 的变化量是 b 的倍数时,1-ax 能保持自己是 b 的倍数,此时就出现新的解了。
因此到最后,如果 x 太小就不断加 b 直到大于等于 0,太大则一直减 b,直到最小正整数解。也就是这么写:
x = (x % b + b) % b;//括号中取模再加,可以处理负数
代码
推导中的所有 x,y 共用全局变量 long long x, y,传递也很方便。
#include<bits/stdc++.h>
using namespace std;
long long x, y;//目前方程真正的解
void exgcd(long long a, long long b)
{
//当前目的:求解 ax + by = gcd(a, b) 这么一个方程
if(b == 0) //a, b不断改变的过程中,b最终必然会成为0
{
//在 b = 0 时方程还要成立? 使 x = 1, y = 0 ,必然成立
x = 1;
y = 7; //建议返回0。不过y = 7能AC,证明了最后一个等式不受最后一个y影响
return;
}
exgcd(b, a % b);//把下一层系数传进去(先求下一个方程的解 )
//现在我们已经拿到了下一个方程的解x, y
long long tx = x;//暂时存一下x,别丢了
x = y;
y = tx - a / b * y;
}
int main()
{
long long a, b;
cin >> a >> b;
exgcd(a, b);
x = (x % b + b) % b;//我们求出来的x必然满足方程,但不一定是最小正整数解,所以要进行答案处理
printf("%lld\n", x);
return 0;
}