数论-欧几里得 (gcd) 与拓展欧几里得 (exgcd)

版权声明:转载请留言 https://blog.csdn.net/qq_40744093 https://blog.csdn.net/qq_40744093/article/details/86755473

                                           欧几里得(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;
}

猜你喜欢

转载自blog.csdn.net/qq_40744093/article/details/86755473
今日推荐