菜鸡学习数论的第五天之 最大公约数,扩展欧几里得

最大公约数与最小公倍数
  若自然数d同时是自然数a和b的约数,这称d是a和b的公约数。在所有a和b的公约数中最大的一个称为a和b的最大公约数,记为gcd(a,b)。
  若自然数m同时是自然数a和b的倍数,这称m是a和b的公倍数。在所有a和b的公倍数中最小的一个称为a和b的最小公倍数,记为lcm(a,b)。

对于任意a,b属于自然数,gcd(a,b)*lcm(a,b)=a*b

证明:

设d=gcd( a , b ),a0 = a / d,b0=b/d,gcd(a0,b0)=1,lcm(a0,b0)=a0*b0.
lcm( a , b )=lcm( a0 * d, b0 * d )=lcm(a0,b0)*d=a0*b0*d=a*b/d
因此lcm(a,b)*gcd(a,b)=a*b;

最大公约数

1).九章算术·更相减损术

对于任意a,b属于自然数,a>=b,gcd(a,b)=gcd(b,a-b)=gcd(a,a-b)
对于任意a,b属于自然数,有gcd(2a,2b)=2gcd(a,b)

证明:

后者显然成立。
    设d是a,b的任意公约数,因为 d | a , d | b ,所以 d | (a-b)(a>=b)。
 因此d也是b,a-b的公约数。反之则成立。故a,b的公约数集合与b,a-b的公约数
 集合相同。对于a,a-b同理,最大公约数也相等。

欧几里得算法

对于任意a,b属于自然数,b不等于0gcd(a,b)=gcd(b,a mod b).

证明:

若a<b,那么 a mod b = a,那么gcd(b,a mod b)=gcd(b,a)=gcd(a,b)
若a大于等于b,设 a = q * b + r (0 <= r <= b),推出 r = a mod b。
             再设 d是a,b的公约数,因此可以推出 d | q * b 。
             那么可以由 d | a, d | q * b,推出 d | ( a - d * q ),
             那么 d | r => d | (a mod b)。
             因此gcd(a,b)=gcd(b,a%a);

代码如下:

int gcd(int a,int b){
    return b==0 ? a : gcd( b % a);
}

   欧几里得算法求最大公约数的时间复杂度为O(log( a + b))。欧几里得算法是最常用的求最大公约数的方法。但是在高精度运算当中,高精度除法(取模)不容易实现,所以我们应当考虑用更相减损法来代替欧几里得算法。

扩展欧几里得算法

对于任意的整数a和b来说,都存在 a * x + b * y = gcd ( a , b )有解。

如何求解?

                ax + by = gcd ( a , b ) = gcd( b , a % b )
b * x1 + ( a % b ) * y1 = gcd ( b , a % b )
          a * x + b * y = b * x1 + ( a % b ) * y1
          a * x + b * y = b * x1 + (a - [ a / b ] * b) * y1
          a * x + b * y = a * y1 + b * x1 -[ a / b ] * b * y1;

由上可知: x = y1 , y = x1 - [ a / b ]*y1.

那么我们可以用递归求解 a * x + b * y = gcd ( a , b )的解,负载度为lg n。

代码如下:

void extend_gcd(int a,int b,int &x,int &y){
	if(b==0){
		x=1,y=0;
		return;
	}
	extend_gcd(b,a%b,x,y);
	int tmp=x;
	x=y;
	y=tmp-(a/b)*y;
}

参考:李煜东《算法竞赛进阶指南》

道阻且长
自己选的路 跪着也要走完

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值