扩展欧几里得算法,线性同余方程
作者:互联网
扩展欧几里得算法
裴蜀定理: 对于任意整数a、b,一定存在非零整数x、y使得\(ax + by = (a,b)\)(a和b的最大公约数)
扩展欧几里得算法可以在求得a、b的最大公约数的同时,能找到整数x、y(其中一个很可能是负数),使它们满足\(ax+by = gcd(a,b)\)
求出的x,y并不是唯一的,但是求出一组\(x_{0}\),\(y_{0}\)就可以求出所有的解\(x = x_{0} - b/d * k,y = y_{0} + a/d * k, k∈Z\)
思路
gcd(a,b) = gcd(b,a mod b)
1.当b为0:
gcd(a,0) = a
ax + 0 * y = a 有x = 1,y = 0
2.当b不为0:
gcd(a,b) = gcd(b,a mod b)
有 by + a%b * x = gcd(b,a mod b)
\(by + (a-\left \lfloor a/b \right \rfloor * b)*x = gcd(b,a\; mod\; b)\)
整理得 $ax + b(y - \left \lfloor a/b \right \rfloor * x) = gcd(b,a; mod; b) $
x没有变,y变成了y-a/b * x
代码
#include<iostream>
using namespace std;
int exgcd(int a,int b,int &x,int &y)
{
if(b == 0)
{
x = 1;
y = 0;
return a;
}
int d = exgcd(b,a%b,y,x);
y = 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 \equiv b (mod\; m)\)
则一定存在y 使得\(ax = my + b\)
所以\(ax - my = b\)
不妨让 y' = -y
则有 \(ax + my = b\) ,当然b能整除gcd(a,m)此方程才有解(即b为a和m的最大公约数的倍数)
此时根据扩展欧几里得算法那求解,事实上求出的是ax + my' = d中的x,让等式右边变成b就把x扩大b/d倍即可(两边同时乘b/d,右边就变成了b)
如果b不能整除gcd(a,m),就输出无解
如果b可以整除gcd(a,m),用扩展欧几里得算法求x,最后结果为x*b/d % m
,d为gcd(a,m),%m是为了保证最后答案在int范围内
代码
#include<iostream>
using namespace std;
typedef long long LL;
int exgcd(int a,int b,int &x,int &y)
{
if(b == 0)
{
x = 1, y = 0;
return a;
}
int d = exgcd(b,a%b,y,x);
y = 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 != 0) puts("impossible"); // 不能整除,无解
else printf("%d\n",(LL)b/d * x % m);
}
return 0;
}
标签:return,gcd,int,欧几里得,exgcd,算法,ax,mod,同余 来源: https://www.cnblogs.com/rdisheng/p/16592300.html