基础数论——EXGCD

1.前言

\(皆さん、こんにちは。\)今天我们来讲 \(EXGCD\) 。(扩展欧几里得)
既然是扩展嘛,那肯定有不扩展的,也就是 \(GCD\)
我们都知道 \(GCD\) 怎么写:

ll GCD(ll X,ll Y){ return Y==0?X:GCD(Y,X%Y);}

然后今天就要讲它的升级版: \(EXGCD\)

2.讲解

上面一段就是 \(GCD\) 的写法,它能够快速解决最大公约数问题。
那么 \(EXGCD\) 就是要解决下面的这个问题:
\(a\times q\equiv c \pmod{p}\)
已知整数 \(q\)\(p\)\(c\) ,求整数 \(a\)
那么我们现在把问题转化一下,显然我们不可能直接对这个问题进行求解。
\(a\times q + b\times p = c\)
\(p\) 相当于就是加上一些 \(p\) 或者减去一些,我们用一个未知量 \(b\) 来表示 \(p\) 的数量。但相较于第一个式子,这个式子更加简洁。
所以现在我们就是要求出 \(a\)\(b\) 的值。
由于是模 \(p\) 意义下的,所以我们令 \(a\)\(b\) 都是非负整数。
我们设 \(d=gcd(q,p)\) ,那么可得以下式子:
\(d \times \dfrac{q}{d} \times a + d \times \dfrac{p}{d} \times b = d \times \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\times q + y\times p = gcd(q,p)\)
然后令 \(x\) 乘上 \(\dfrac{c}{gcd(q,p)}\) 就是 \(a\) 的值了。
我们设 \(x_1\)\(y_1\)\(gcd(q,p)\) 的解。
\(x_1 \times q + y_1 \times p = gcd(q,p)\)
然后设 \(x_2\)\(y_2\)\(gcd(p,q\ mod\ p)\) 的解。
\(x_2 \times p + y_2 \times (q\ mod\ p) = gcd(p,q\ mod\ p)\)
显然 \(gcd(p,q\ mod\ p)\)\(gcd(q,p)\) 是相等的,都是求 \(p\)\(q\) 的最大公约数,所以得:
\(x_2 \times p + y_2 \times (q\ mod\ p) = gcd(q,p)\)
接下来把 ③ 式的 “\(q\ mod\ p\)” 展开得:
\(x_2 \times p + y_2 \times q - y_2 \times \left\lfloor\dfrac{q}{p}\right\rfloor \times p = gcd(q,p)\)
由 ①、③ 二式得, \(x_1=y_2\)\(y_1=x_2-y_2 \times \left\lfloor\dfrac{q}{p}\right\rfloor\)
所以我们发现, \(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\n",X%P);
	return 0;
}

\(Thanks\ for\ Watch.\)
\(皆さん、さよなら。\)

posted @ 2020-06-03 15:54  eromangasensei  阅读(272)  评论(0编辑  收藏  举报