luogu1082 同余方程

题目大意:求$$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;
}

  

原文地址:https://www.cnblogs.com/headboy2002/p/8845986.html