luogu1082 同余方程
题目大意:求$$ax\equiv 1(\ \mathrm{mod}\ m)$$的最小正整数解。
因为$ax-1|m$,故令$ax-1=-ym$,原方程就变成了$ax+my=1$。根据bezout定理此方程有解当且仅当$\gcd(a, m)=1$成立,然后解方程$ax+my=\gcd(a,m)$即可。
先不考虑原题,若要解方程$$ax+by=\gcd(a,b)$$,要用到扩展欧几里得算法。当$b=0$时,显然$x=1,y=0$。因为$$\gcd(a,b)=\gcd(b,a\ \mathrm{mod}\ b), a\ \mathrm{mod}\ b=a-\lfloor \frac{a}{b}\rfloor b$$,所以如果知道了$$bx'+(a-\lfloor \frac{a}{b}\rfloor b)y'=\gcd(b, a\ \mathrm{mod}\ b)=\gcd(a, b)$$,将等式左面倒一倒就变成了$$ay'+b(x'-\lfloor \frac{a}{b}\rfloor y')=\gcd(a,b)$$。所以令当前的$x=y', y=x'-(a/b)*y'$便是一个解。于是在欧几里得算法的基础上加上这一句即可。
回到原题,人家要求最小正整数解,因为该同余方程$ax\equiv 1(mod m)$的通解为所有模m与x0同余的整数($ax+amk=a(x+mk)\equiv 1(\ \mathrm{mod}\ m)$依然成立),我们要将解转移使$x\in [1,m)$。故将以上解出的$x$进行(x%m+m)%m。x%=m时,$x\in (-m,m)$。再加m模m是为了处理x是负数的情况。
#include <cstdio> #include <cstring> using namespace std; long long Exgcd(long long a, long long b, long long &x, long long &y) { if (b == 0) { x = 1; y = 0; return a; } long long d = Exgcd(b, a%b, x, y); long long tx = x; x = y; y = tx - (a / b)*y; return d; } long long Inv(long long a, long long m) { long long x, y; Exgcd(a, m, x, y); return (x%m + m) % m; } int main() { long long a, m; scanf("%lld%lld", &a, &m); printf("%lld\n", Inv(a, m)); return 0; }