数论 _ 扩展欧几里得算法
裴蜀定理
对于任意正整数a,b, 一定存在整数x, y,使得 \(ax + by = (a, b)\)
因为\((a,b)\)为常数,令\(d= (a, b)\)
则\(ax + by = d\)
扩展欧几里得算法就是用于求上面的x和y。
注意:
x和y不唯一。
证明
因为
\[gcd(a, b) = gcd(b, a\%b)
\]
\[bx' + (a \% b)y' = gcd(b, a\%b)
\]
而
\[bx' + (a-\lfloor a/b \rfloor*b)y' = gcd(b, a\%b)
\]
\[ay' + b(x'- \lfloor {a / b} \rfloor*y') = gcd(b, a\%b) = gcd (a, b)
\]
故而
\[x = y', \quad y = x' - \lfloor {a/b} \rfloor*y'
\]
因此可以采取递归算法 先求出下一层的x′和y′ 再利用上述公式回代即可。
代码:
#include <iostream>
#include <algorithm>
using namespace std;
int exgcd(int a, int b, int &x, int &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()
{
int n;
scanf("%d", &n);
while (n -- )
{
int a, b;
scanf("%d%d", &a, &b);
int x, y;
exgcd(a, b, x, y);
printf("%d %d\n", x, y);
}
return 0;
}
应用
线性同余方程
\(a*x ≡ b (\mod m)\)
等价于 \(a*x-m* y' = b\)(x,y'是未知数)
设\(y = y'\),则有 \(a*x+m* y = b\)
根据 裴蜀定理,上述等式有解当且仅当 b是gcd(a,m)的倍数。
所以可以用拓展欧几里得算法
代码:
#include <iostream>
#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 d = exgcd(b, a % b, y, x);
y -= a / b * x;
return d;
}
int main()
{
int n;
scanf("%d", &n);
while (n -- )
{
int a, b, m;
scanf("%d%d%d", &a, &b, &m);
int x, y;
int d = exgcd(a, m, x, y);
if (b % d) puts("impossible");
else printf("%d\n", (LL)b / d * x % m);
}
return 0;
}