扩展欧几里得算法
欧几里得算法为求 gcd(a, b)
该式子基于裴蜀定理。
gcd(a,b) = gcd(b, a % b)
a % b = a - [a/b] * b
即:
a*x + b*y = b*x + (a - [a/b]*b) * y
再进一步转化, gcd(b, a % b) = gcd(a % b, b % a % b)
且 gcd 有边界条件, 故可以通过递归来求得 x, y
当 b = 0 时, x = 1, y = 0
可得
`ax + by = ay + b(x - [a/b]*y)
void exgcd(int a, int b, int &x, int &y)
{
if(!b)
{
x = 1, y = 0;
return;
}
exgcd(b, a % b, x, y);
int t = x;
x = y, y = t - a/b*y;
}
线性同余方程
a*x - a*x / m * m = b
设 y = -[a*x/m]
则化为:
a*x + m*y = b
显然就是 扩展欧几里得算法。
若b是 gcd(a,m) 的公约数倍数, 那就有解
那么就直接求出 exgcd(a,m,x,y)后的x
, 和 gcd(a,m)
, 若
b 是 gcd(a,m)
的倍数就输出 x * (b/d) % m
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
int exgcd(int a, int b, int &x, int &y)
{
if(!b)
{
x = 1, y = 0;
return a;
}
int t = exgcd(b, a % b, y, x);
y = y - a/b * x;
return t;
}
int n;
int main()
{
cin >> n;
while(n--)
{
int a,m,b,x,y;
scanf("%d%d%d", &a, &b, &m);
int d = exgcd(a,m,x,y);
if(b % d) cout << "impossible\n";
else printf("%d\n", (LL)x * (b / d) % m);
}
return 0;
}