扩展欧几里得算法
Posted lbzbk
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了扩展欧几里得算法相关的知识,希望对你有一定的参考价值。
扩展欧几里得算法
前置条件:需要掌握裴蜀定理和欧几里得算法
裴蜀定理:
对于不全为0的整数a, b,一定有整数x, y,使得ax + by = gcd(a, b)
欧几里得算法:
gcd(a, b) == gcd(b, a % b)
假设有组特解x0, y0,使得ax0 + by0 = gcd(a, b)
则必有bx1 + (a % b)y1 = gcd(b, a % b) = gcd(a, b)
其中(a % b) = a - a / b * b
整理得:b(x1 - a / b * y1) + ay1 = ax0 + by0
即:y0 = x1 - a / b * y1, x0 = y1
所以x0 是由 y1转化而来, y0 是由 x1 - a / b * y1转化而来,因此递归时使用exgcd(b, a % b, y, x), y -= a / b * x
若要使ax + by = n(n为ax + by可以取到的数)
设d = gcd(a, b), 那么n % d == 0,n一定是d的倍数
他的特解是x0, y0,而通解则是:
x = n / d * x0 + k * b / d(k为任意整数)
y = n / d * y0 + k * a / d
#include <iostream>
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;
cin >> n;
while (n --)
int a, b, x, y;
cin >> a >> b;
exgcd(a, b, x, y);
cout << x << \' \' << y << endl;
return 0;
扩展欧几里得算法+推论
什么是扩展欧几里得?
扩展欧几里得算法是建立在欧几里得算法(gcd)之上。
首先,我们知道有(a*x+b*y=gcd(a,b))
我们怎么求这个(x,y)呢?
这时候我们就得使用exgcd算法,我们来推导一下吧!
(a*x+b*y=gcd(a,b))
(a*x+b*y=gcd(b,a\% b))
(a*x+b*y=b*x'+(a- left lfloor frac{a}{b}
ight
floor*b)*y')
(a*x+b*y= a*y'+b*(x'-left lfloor frac{a}{b}
ight
floor*y'))
因此,根据系数对应,我们得到了
(x=y'),(y=x'-left lfloor frac{a}{b} ight floor*y')
那这个式子我们显然可以在递归里面顺带算出来嘛。
再想一想,我们gcd的递归出口为(b=0),即(a*x=gcd(a,b)),所以说我们的(x,y)的递归出口也为(x=1,y=0)
代码大概长这样qwq:
long long exgcd(long long A,long long B,long long &x,long long &y)
{
if(B==0)
{
x=1,y=0;
return A;
}
long long t=exgcd(B,A%B,x,y),tx=x;
x=y;
y=tx-(A/B)*y;
return t;
}
酱紫,我们就求出了(x,y)的一组解(x_0,y_0)
进一步推导
如果我们要求x的最小正整数解,那不免要求x的通项公式。
首先我们的推导建立在已经求出了一组((x_0,y_0))使得(a imes x+b imes y=gcd(a,b))
我们要求的(x)的通项公式是建立在(x_0)之上的,我们假设(x=x_0+p),(y=y_0-q)
现在问题就变为了如何求这个(p)。
原式变为:
[a(x_0+p)+b(y_0-q)=gcd(a,b)]
展开得:
[a*x_0+a*p+b*y_0-q*b=gcd(a,b)]
与原式(a*x_0+b*y_0=gcd(a,b))相减得
[ap=bq]
[p=frac{b*q}{a}]
我们设(d=gcd(a,b)),有(a=a'*d),(b=b'*d)
将上一个式子上下同时除以(d)得
[p=frac{b'*q}{a'}]
因为(p)为正整数,因此我们的(q)至少等于(a')才能使得(p)的取值最小
[p=b*frac{a'}{a}=b*frac{1}{d}=b*frac{1}{gcd(a,b)}]
解毕,我们得到了(x)的通项公式(x=x_0+k*frac{b}{gcd(a,b)})
.
完结撒花(*′???`)?
以上是关于扩展欧几里得算法的主要内容,如果未能解决你的问题,请参考以下文章