1.前言
(皆さん、こんにちは。)今天我们来讲 (EXGCD) 。(扩展欧几里得)
既然是扩展嘛,那肯定有不扩展的,也就是 (GCD) 。
我们都知道 (GCD) 怎么写:
ll GCD(ll X,ll Y){ return Y==0?X:GCD(Y,X%Y);}
然后今天就要讲它的升级版: (EXGCD) 。
2.讲解
上面一段就是 (GCD) 的写法,它能够快速解决最大公约数问题。
那么 (EXGCD) 就是要解决下面的这个问题:
(a imes qequiv c pmod{p})
已知整数 (q) , (p) , (c) ,求整数 (a) 。
那么我们现在把问题转化一下,显然我们不可能直接对这个问题进行求解。
(a imes q + b imes p = c)
模 (p) 相当于就是加上一些 (p) 或者减去一些,我们用一个未知量 (b) 来表示 (p) 的数量。但相较于第一个式子,这个式子更加简洁。
所以现在我们就是要求出 (a) 和 (b) 的值。
由于是模 (p) 意义下的,所以我们令 (a) , (b) 都是非负整数。
我们设 (d=gcd(q,p)) ,那么可得以下式子:
(d imes dfrac{q}{d} imes a + d imes dfrac{p}{d} imes b = d imes dfrac{c}{d})
由于 (gcd(q,p) mid q) 且 (gcd(q,p) mid p) ,那么 (dfrac{q}{d}) 和 (dfrac{p}{d}) 就是整数,那么 (dfrac{c}{d}) 也是整数,所以 (gcd(q,p) mid c) 。
那么如果我们求解了以下式子:
(x imes q + y imes p = gcd(q,p))
然后令 (x) 乘上 (dfrac{c}{gcd(q,p)}) 就是 (a) 的值了。
我们设 (x_1) , (y_1) 为 (gcd(q,p)) 的解。
(x_1 imes q + y_1 imes p = gcd(q,p)) ①
然后设 (x_2) , (y_2) 为 (gcd(p,q mod p)) 的解。
(x_2 imes p + y_2 imes (q mod p) = gcd(p,q mod p))
显然 (gcd(p,q mod p)) 和 (gcd(q,p)) 是相等的,都是求 (p) 和 (q) 的最大公约数,所以得:
(x_2 imes p + y_2 imes (q mod p) = gcd(q,p)) ②
接下来把 ③ 式的 “(q mod p)” 展开得:
(x_2 imes p + y_2 imes q - y_2 imes leftlfloordfrac{q}{p}
ight
floor imes p = gcd(q,p)) ③
由 ①、③ 二式得, (x_1=y_2) 、 (y_1=x_2-y_2 imes leftlfloordfrac{q}{p}
ight
floor) 。
所以我们发现, (p) 和 (q) 的解是由 (q) 和 ((p mod q)) 推过来的,所以我们可以在求 (q) 和 (p) 的最大公约数递归返回的过程中求解 (x) 和 (y) 。
当 (p) 为 (0) 的时候 (q) 为最大公约数,此时的 (x=1) , (y=0) 。
这样 (EXGCD) 就讲完了。
3.代码
#include<bits/stdc++.h>
using namespace std;
long long Q,P,X,Y;
long long Exgcd(long long Q,long long P,long long &X1,long long &Y1){
if(!P){ X1=1;Y1=0; return Q;}
long long X2,Y2,D=Exgcd(P,Q%P,X2,Y2);
X1=Y2;Y1=X2-(Q/P)*Y2;
return D;
}
int main(){
scanf("%lld%lld",&Q,&P);
Exgcd(Q,P,X,Y);
while(X<0) X=X+P;
printf("%lld
",X%P);
return 0;
}
(Thanks for Watch.)
(皆さん、さよなら。)