题目大意:求$$axequiv 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} floor b$$,所以如果知道了$$bx'+(a-lfloor frac{a}{b} floor b)y'=gcd(b, a mathrm{mod} b)=gcd(a, b)$$,将等式左面倒一倒就变成了$$ay'+b(x'-lfloor frac{a}{b} floor y')=gcd(a,b)$$。所以令当前的$x=y', y=x'-(a/b)*y'$便是一个解。于是在欧几里得算法的基础上加上这一句即可。
回到原题,人家要求最小正整数解,因为该同余方程$axequiv 1(mod m)$的通解为所有模m与x0同余的整数($ax+amk=a(x+mk)equiv 1( mathrm{mod} m)$依然成立),我们要将解转移使$xin [1,m)$。故将以上解出的$x$进行(x%m+m)%m。x%=m时,$xin (-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
", Inv(a, m));
return 0;
}