朴素欧几里得:辗转相除法求gcd(a,b)(a和b的最大公约数),gcd(a,b)=gcd(b,a%b),不是重点不多说了
拓展欧几里得:必然存在整数对 x,y ,使得 gcd(a,b)=ax+by。
首先证明这个命题成立
设a>b
(1)b=0时,gcd(a,b)=a,x=1,y=0
(2)ab≠0 gcd(a,b)=ax+by 同理存在gcd(b,a%b)=bx1+(a%b)y1
∵gcd(a,b)=gcd(b,a%b)
∴ax+by=ax1+(a%b)y1
ax+by=bx1+(a-(a/b)*b)y1 这一步特殊而重要,这里的“/”指的是计算机中的除并向下取整
ax+by=ay1+b(x1-(a/b)y1)
因为这个等式恒成立,所以x=y1,y=x1-(a/b)y1,
又因为当b=0时,x=1,y=0,这样就可以确保递推能求解x,y了,得证
写道题做代码样例
NOIP2012d2t1 同余方程
原题链接https://vijos.org/p/1781
ax ≡ 1 (mod b)可以转化为 求最小正整数x使ax-by=1,一样可解
求出任意一组解,再%b出最小值
#include <cstdio>
#include <cstring>
typedef long long lld;
lld a,b,x,y;
lld exgcd(lld a,lld b,lld &x,lld &y){
if(b==0){
x=1,y=0;
return a;
}
lld ans=exgcd(b,a%b,x,y);
lld t=x;
x=y,y=t-(a/b)*y;
return ans;
}
int main(){
freopen("mod.in","r",stdin);
freopen("mod.out","w",stdout);
scanf("%lld%lld",&a,&b);
lld ans=exgcd(a,b,x,y);
if(ans==1){
x=((x%b)+b)%b;
printf("%I64d",x);
}
return 0;
}
其实像我这样数学不好的,一遇这个就懵*,还是得多练,我这篇其实不过是刚刚弄懂老师讲的,再重新推一遍罢了。