思路:
1、扩展欧几里得
我们先回忆一下欧几里得算法(辗转相除法):
如果 d | a, d | b 那么 存在x , y 使得 d | ax + by
gcd (a, b) = gcd (b, a % b)
int gcd(int a, int b) { return b ? gcd (b, a % b) : a; }
扩展欧几里得算法用到一个重要的定理 —— 裴蜀定理
有任意一对正整数a, b,那么一定存在非零正整数x,y,使得 ax + by = gcd(a, b)
ax + by = d .... (1)
by + (a % b)x = d
a % b = a - |a/b| * b
化简得 ax + b(y - |a/b| * x) = d ... (3)
联立(1)(3)得 y = y - |a/b| * x
int exgcd(LL a, LL b, LL& x, LL& y) { if (!b) { x = 1, y = 0; return a; } int d = exgcd(b, a % b, y, x); y -= a / b * x; return d; }
2、同余方程
ax 1 (mod b)
等价于 ax + by = 1
又因为 ax + by = gcd (a, b)
a, b互质
只需求exgcd(a, b, x, y)
#include <iostream>
using namespace std;
typedef long long LL;
LL a, b, x, y;
int exgcd(LL a, LL b, LL& x, LL& y)
{
if (!b)
{
x = 1, y = 0;
return a;
}
int d = exgcd(b, a % b, y, x);
y -= a / b * x;
return d;
}
int main()
{
cin >> a >> b;
int d = exgcd(a, b, x, y);
cout << (x + b) % b << endl;
return 0;
}