版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Ronaldo7_ZYB/article/details/89258049
扩展欧几里得算法Exgcd
Exgcd算法内容
给定
a,b,c,d,求解
ax +by = gcd(a,b)中的任意正数解
(x,y)
Exgcd求解一组整数解
我们可以根据裴蜀定理,证明方程一定有解。
由于欧几里得算法
gcd(a,b) = gcd(b,a % b),则有:
ax +by =bx + (a % b)∗y
用除法代替取模,则:
ax +by =bx′+y′(a−[a/b]∗b)
通过乘法分配律和结合律的运算可得:
ax+by=ay′+b(x′−[a/b]∗y′)
其中,
x′和
y′是方程
bx+y(a−[a/b]∗b)=gcd(b,a%b)的解,用来借助这个已经求得的
x′和
y′结合已知的
a和
b推得现在的解
x,y.其中
a和
b不变。我们可以通过递归来求。
递归的边界:
ax+by=gcd(a,0)时,即
b=0时,
x=1 y=0.
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int x,y;
int exgcd(int a,int b)
{
if (b==0)
{
x=1;
y=0;
return a;
}
int n=exgcd(b,a%b);
int t=x;
x=y;
y=t-a/b*y;
return n;
}
int main(void)
{
int a,b;
cin>>a>>b;
cout<<exgcd(a,b)<<endl;
cout<<x<<' '<<y<<endl;
return 0;
}
Exgcd算法拓展
根据裴蜀定理,我们可以得到如下方程的解:
ax + by = c, gcd(a,b) ∣ c
因此在代码实现上,我们递归到了边界是换一个处理,令
x = c/gcd(a,b), y = 0。
代码实现和上述代码基本相似。
Exgcd算法通解
对于方程
ax + by = c, gcd(a,b) ∣ c来说,如果有一组解
(x0,y0),我们可以用含有
x0和
y0a来解释这一个方程的通解。
我们可以通过相乘再相加抵消,来证明这一串代数式属于Exgcd算法的通解:
(x0 + k∗gcd(a,b)b , y0 + k∗gcd(a,b)a)
显然,两个数字乘上
a,b以后再相加,结果一定等于
x0+y0 。
k取任意整数。
线性同余方程
线性同余方程的一组解
现在我们需要求解有关
x的线性同余方程:
a ∗ x ≡ b (mod m)
变形一下,就变成了:
a∗x − b ≡ 0 (mod m)
然后我们就可以发现
a∗x − b一定是
m的倍数,因此我们设是
m的
−y倍,则可以将同余式变形为等式:
a∗x −b = −y∗m⟹a∗x+y∗m = b
现在我们就变形为了一个扩展欧几里得算法的形式,即可运用上述算法求出对应的解
x。
线性同余方程的通解
我们知道扩展欧几里得的通解形式是:
(x0 + k∗gcd(a,b)b , y0 + k∗gcd(a,b)a)
再结合线性同余方程的欧几里得式:
a∗x+y∗m = b
我们考虑对每一个
x求出通解:
- 不难知道在这里m就是通解形式中的b,而任意一个数加上了
k∗gcd(a,m)m以后,一定有:
k∗gcd(a,m)m≡ x
因此只要满足
gcd(a,m)m与x同余的数就是方程的通解。
线性同余方程的最小正整数解
我们知道了方程的通解,则另
P = gcd(a,m)m,对于任意一个整数解
x0,则有最小正整数解:
x = (x % P + P) % P
小结
Exgcd和线性同余方程是一个数论的模型,要熟记结论,灵活应用。许多的扩展和变形要需要以这两个算法为根本。