最大公约数简谈

根据教师课件,写成本文。未经允许,禁止转载。

gcd ⁡ \gcd gcd,即最大公约数,指的是几个整数中公有的约数中最大的一个。

问题

已知 a , b a,b a,b,求 gcd ⁡ ( a , b ) \gcd(a,b) gcd(a,b)

方法一:枚举法

min ⁡ ( a , b ) \min(a,b) min(a,b) 1 1 1 枚举,找到第一个 x x x 符合题意,就退出循环。

时间复杂度 O ( min ⁡ ( a , b ) ) \mathcal O(\min(a,b)) O(min(a,b))

方法二:分解质因数

a = p 1 x 1 p 2 x 2 … p n x n a=p_1^{x_1}p_2^{x_2}\dots p_n^{x_n} a=p1x1p2x2pnxn b = p 1 y 1 p 2 y 2 … p n y n b=p_1^{y_1}p_2^{y_2}\dots p_n^{y_n} b=p1y1p2y2pnyn,其中 x i , y i ≥ 0 x_i,y_i\ge0 xi,yi0 且不同时为 0。

gcd ⁡ ( a , b ) = p 1 min ⁡ ( x 1 , y 1 ) p 2 min ⁡ ( x 2 , y 2 ) … p 3 min ⁡ ( x 3 , y 3 ) \gcd(a,b)=p_1^{\min(x_1,y_1)}p_2^{\min(x_2,y_2)}\dots p_3^{\min(x_3,y_3)} gcd(a,b)=p1min(x1,y1)p2min(x2,y2)p3min(x3,y3)

时间复杂度 O ( min ⁡ ( a , b ) ) \mathcal O(\sqrt{\min(a,b)}) O(min(a,b) )

void Gcd()
{
	for(int x=2;x*x<=min(a,b);x++)
	{
		while (a % x==0 && b % x==0) {a/=x;b/=x;ans*=x;}
		while (a % x==0)a/=x;
    	while (b % x==0)b/=x;
	} 
	if (a % b==0)ans*=b;
    else if (b % a==0)ans*=a;
    printf("%d",ans);
}

方法三:辗转相除(欧几里得算法)

定理: gcd ⁡ ( a , b ) = gcd ⁡ ( b , a % b ) \gcd(a,b)=\gcd(b,a\%b) gcd(a,b)=gcd(b,a%b)

证明:

gcd ⁡ ( a , b ) = p \gcd(a,b)=p gcd(a,b)=p,则有 a = a ′ ∗ p , b = b ′ ∗ p , gcd ⁡ ( a ′ , b ′ ) = 1 a=a'*p,b=b'*p,\gcd(a',b')=1 a=ap,b=bp,gcd(a,b)=1

a % b = a − ⌊ a b ⌋ ∗ b = a ′ ∗ p − ⌊ a b ⌋ ∗ b ′ ∗ p = p ∗ ( a ′ − ⌊ a b ⌋ ∗ b ′ ) a\%b=a-\lfloor\frac{a}{b}\rfloor *b=a'*p-\lfloor\frac{a}{b}\rfloor*b'*p=p*(a'-\lfloor\frac{a}{b}\rfloor*b') a%b=abab=apbabp=p(abab)

gcd ⁡ ( b , a % b ) = gcd ⁡ ( b ′ ∗ p , p ∗ ( a ′ − ⌊ a b ⌋ ∗ b ′ ) ) = p ∗ gcd ⁡ ( b ′ , a ′ − ⌊ a b ⌋ ∗ b ′ ) \gcd(b,a\%b)=\gcd(b'*p,p*(a'-\lfloor\frac{a}{b}\rfloor*b'))=p*\gcd(b',a'-\lfloor\frac{a}{b}\rfloor*b') gcd(b,a%b)=gcd(bp,p(abab))=pgcd(b,abab)

现证明 gcd ⁡ ( b ′ , a ′ − ⌊ a b ⌋ ∗ b ′ ) = 1 \gcd(b',a'-\lfloor\frac{a}{b}\rfloor*b')=1 gcd(b,abab)=1,使用反证法。假设 g c d ( b ′ , a ′ − ⌊ a b ⌋ ∗ b ′ ) = t ( t > 1 ) gcd(b',a'-\lfloor\frac{a}{b}\rfloor*b')=t(t>1) gcd(b,abab)=t(t>1)

b ′ = b ′ ′ ∗ t b'=b''*t b=bt a ′ − ⌊ a b ⌋ ∗ b ′ = c ′ ∗ t a'-\lfloor\frac{a}{b}\rfloor*b'=c'*t abab=ct

a ′ = c ′ ∗ t + ⌊ a b ⌋ ∗ b ′ = c ′ ∗ t + ⌊ a b ⌋ ∗ b ′ ′ ∗ t = t ∗ ( c ′ + ⌊ a b ⌋ ∗ b ′ ′ ) a'=c'*t+\lfloor\frac{a}{b}\rfloor*b'=c'*t+\lfloor\frac{a}{b}\rfloor*b''*t=t*(c'+\lfloor\frac{a}{b}\rfloor*b'') a=ct+bab=ct+babt=t(c+bab)

gcd ⁡ ( a ′ , b ′ ) ≥ p \gcd(a',b')\ge p gcd(a,b)p,与 gcd ⁡ ( a ′ , b ′ ) = 1 \gcd(a',b')=1 gcd(a,b)=1 矛盾,因此 gcd ⁡ ( b ′ , a ′ − ⌊ a b ⌋ ∗ b ′ ) = 1 \gcd(b',a'-\lfloor\frac{a}{b}\rfloor*b')=1 gcd(b,abab)=1

gcd ⁡ ( b , a % b ) = p = gcd ⁡ ( a , b ) \gcd(b,a\%b)=p=\gcd(a,b) gcd(b,a%b)=p=gcd(a,b)


时间复杂度 O ( log ⁡ ( max ⁡ ( a , b ) ) ) \mathcal O(\log(\max(a,b))) O(log(max(a,b)))

分析:

  1. a > b a>b a>b

    a > 2 b a>2b a>2b,则 b ≤ a 2 b\le \frac{a}{2} b2a,规模减小一半。反之 a < 2 b a<2b a<2b,则 a % b < a 2 a\%b<\frac{a}{2} a%b<2a

    因此时间复杂度是 log ⁡ \log log 级别。

  2. 斐波那契分析:传送门


int Gcd(int a,int b)
{
    if (b==0) return a;
    else return Gcd(b,a % b);
}

方法四:二进制法

a < b a<b a<b 时, gcd ⁡ ( a , b ) = gcd ⁡ ( b , a ) \gcd(a,b)=\gcd(b,a) gcd(a,b)=gcd(b,a)

a = b a=b a=b gcd ⁡ ( a , b ) = a \gcd(a,b)=a gcd(a,b)=a

a , b a,b a,b 同为偶数时, gcd ⁡ ( a , b ) = 2 ∗ gcd ⁡ ( a 2 , b 2 ) \gcd(a,b)=2*\gcd(\frac{a}{2},\frac{b}{2}) gcd(a,b)=2gcd(2a,2b)

a a a 为偶数, b b b 为奇数时, gcd ⁡ ( a , b ) = gcd ⁡ ( a 2 , b ) \gcd(a,b)=\gcd(\frac{a}{2},b) gcd(a,b)=gcd(2a,b)

a a a 为奇数, b b b 为偶数时, gcd ⁡ ( a , b ) = gcd ⁡ ( a , b 2 ) \gcd(a,b)=\gcd(a,\frac{b}{2}) gcd(a,b)=gcd(a,2b)

a , b a,b a,b 为奇数时, gcd ⁡ ( a , b ) = gcd ⁡ ( a − b , b ) \gcd(a,b)=\gcd(a-b,b) gcd(a,b)=gcd(ab,b)

注:此法适合高精度求最大公约数。

int Gcd(int m,int n)
{
    if (m==n) return m;
    if (m<n) return Gcd(n,m);
    if (m & 1==0) return (n & 1==0)? 2*Gcd(m/2,n/2):Gcd(m/2,n);
    return (n & 1==0)? Gcd(m,n/2): Gcd(n,m-n);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值