• 浅谈最大公约数


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

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

    问题

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

    方法一:枚举法

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

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

    方法二:分解质因数

    \(a=p_1^{x_1}p_2^{x_2}\dots p_n^{x_n}\)\(b=p_1^{y_1}p_2^{y_2}\dots p_n^{y_n}\),其中\(x_i,y_i\ge0\) 且不同时为 0。

    \(\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)}\)

    时间复杂度 \(\mathcal O(\sqrt{\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)=p\),则有 \(a=a'*p,b=b'*p,\gcd(a',b')=1\)

    \(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')\)

    \(\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'-\lfloor\frac{a}{b}\rfloor*b')=1\),使用反证法。假设 \(gcd(b',a'-\lfloor\frac{a}{b}\rfloor*b')=t(t>1)\)

    \(b'=b''*t\)\(a'-\lfloor\frac{a}{b}\rfloor*b'=c'*t\)

    \(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'')\)

    \(\gcd(a',b')\ge p\),与 \(\gcd(a',b')=1\) 矛盾,因此 \(\gcd(b',a'-\lfloor\frac{a}{b}\rfloor*b')=1\)

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


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

    分析:

    1. \(a>b\)

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

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

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


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

    方法四:二进制法

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

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

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

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

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

    \(a,b\) 为奇数时,\(\gcd(a,b)=\gcd(a-b,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);
    }
    
  • 相关阅读:
    封装

    如何通过命令行窗口查看sqlite数据库文件
    标签控件
    信息提示框
    循环
    数组
    switch
    成员局部变量
    变量
  • 原文地址:https://www.cnblogs.com/Livingston/p/16218650.html
Copyright © 2020-2023  润新知