欧几里得(gcd)
[用途]
求最大公约数 时间复杂度O(log n)
[结论]
gcd(a,b)=gcd(b,a%b)
[证明]
当a<b时,程序运行一次又回到了gcd(b,a)
所以我们直接证明a>=b的情况即可
当r=a%b==0时:
a是b的倍数,显然最大公约数是b,这不刚好是递归出口吗,则gcd(a,b)=gcd(b,a%b)=gcd(b,0)得证(a==b的情况已经包含在内)
当r>0,即a>b时:
我们知道,任意两个非零正整数都有公约数,取a,b的一个公约数为x,x是正整数;
设 a=kb+r, a=nx, b=mx; k,r,n,m均为正整数;
则a%b=r=a-kb=nx-kmx=(n-km)x>0;
又因为r,x是正整数,则n-km也是正整数
所以x也是r的公约数,可想而知,任取a,b的一个公约数都是r的公约数,最大公约数当然也是了,所以gcd(a,b)=gcd(b,a%b)
[代码]
typedef long long LL;
LL gcd(LL a,LL b)
{
if(!b)return a;
return gcd(b,a%b);
}
拓展欧几里得(exgcd)
[用途]
求解ax+by=gcd(a,b) 时间复杂度O(log n)
[结论]
x1=y2
y1=x2-a/b*y2
[证明]
根据gcd(a,b)=gcd(b,a%b),设gcd(a,b)=gcd;
有
ax1+by1=gcd;
bx2+(a-a/b *b)y2=gcd;
则
ax1+by1=bx2+ay2-a/b *by2
ax1+by1=ay2+b(x2-a/b*y2)
所以
x1=y2
y1=x2-a/b*y2
[代码]
typedef long long LL;
LL exgcd(LL a,LL b,LL &x,LL &y)
{
if(!b){
x=1;
y=0;
return a;
}
LL gcd=exgcd(b,a%b,x,y);
LL x2=x,y2=y;
x=y2;
y=x2-a/b*y2;
return gcd;
}
稍微简化下
typedef long long LL;
LL exgcd(LL a,LL b,LL &x,LL &y)
{
if(!b){
x=1;
y=0;
return a;
}
LL gcd=exgcd(b,a%b,y,x);
y-=a/b*x;
return gcd;
}