• C++求最大公因数(gcd)的六重境界


    前言 

            众所周知,最大公因数(gcd)是C++程序中第二常见的函数(仅次于判素数)。正因此,一个简单的gcd也能被不同的OIER写出不同的“境界”。

            话不多说,直接开始!


    第一境界:暴力枚举!

            如果你是一个连while循环都没写过的超级蒟蒻(天南星科植物魔芋属植物),那么你该怎么写判最大公因数程序?

            答案很简单:暴力枚举!

            我们可以用循环变量i直接从A,B中的小值直接反向枚举到1,如果能同时被A,B整除,直接输出i就行了。

            这样写虽然长(其实也不是很长),但也是最直白的思路了:

    1. int gcd(int a,int b)
    2. {
    3. for(int i=min(a,b);i>=1;i--)
    4. if(a%i==0&&b%i==0) return i;
    5. }

             但这样写的时间复杂度是O(min(a,b)),因此一旦A,B都特别大的时候(比如说都是2的31次方),这种方法的运行速度将会比乌龟还慢,自然会时间超限(TLE)。


    第二境界:辗转相除法

            很快,你就学会了while循环,同时也去百度上搜索了辗转相除法

            辗转相除法就是定义一个变量R来储存A模B的值,再将A的值设为B,B的值设为R。以此类推,直到B=0为止。然后直接输出A就行了。

            这样写虽然长了一点,但是时间复杂度获得了飞跃性的提升:

    1. int gcd(int a,int b)
    2. {
    3. while(b>0)
    4. {
    5. int r=a%b;
    6. a=b;b=r;
    7. }
    8. return a;
    9. }

            作为一名初学者,会这段程序就够了(bushi)。 


    第三境界:递归

           一个寒假过去了,曾经的那名蒟蒻终于学会了递归。

            你发现,用递归写最大公因数又快了很多。

            用递归写最大公因数,还是基于辗转相除法。这样写,当A模B等于0时,返回B;否则返回递归求解B和A模B的最大公因数的值。

            于是,你写出了一段递归求解的程序:

    1. void gcd(int a,int b)
    2. {
    3. if(a%b==0) return b;
    4. else return gcd(b,a%b);
    5. }

            可这样写在OJ上没有通过。奇怪,百度上不是那么写的吗?

            事实上,根据辗转相除法的性质,应该是在B等于0是返回此时A的值,而不是在当A模B等于0时返回B的值。

            你把程序改了一下,果然通过(AC)了这道题目:

    1. int gcd(int a,int b)
    2. {
    3. if(b==0) return a;
    4. else return gcd(b,a%b);
    5. }

    第四境界:三元组

            你在《信息学奥赛一本通》中学到了有关三元组的知识。

            "啊?三元组?这似乎能运用到gcd上啊。"

            事实上,三元组在时间复杂度上与递归相比并没有变快。但是,使用三元组,原本两行的代码变成了一行。

            于是,求最大公因数的算法由两行变成了一行:

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

    第五境界:编译器自带函数!

            前段时间,你在一篇题解上发现了__gcd这个编译器自带函数。

            于是你一口气写出了判最大公因数的整个程序(真的只用了一口气的时间):

    1. #include
    2. using namespace std;
    3. int main()
    4. {
    5. int a,b;
    6. cin>>a>>b;
    7. cout<<__gcd(a,b);
    8. return 0;
    9. }

    第六境界:从__gcd变回gcd

            但作为一名热爱共产党的新时代青少年,怎么能在gcd的前面加上两道杠呢?(你可以用键盘打出"gcd"试试)。

            难道是退回第四境界呢?当然不行。作为一名合格的OIER,写的算法当然要及时更新迭代,不可以落后。

            于是,你请出了#define语句(话说#define是真的好用),用它写出了“货真价实”的gcd:

    1. #include
    2. #define gcd __gcd
    3. using namespace std;
    4. int main()
    5. {
    6. int a,b;
    7. cin>>a>>b;
    8. cout<<gcd(a,b);
    9. return 0;
    10. }

    (无疾而终?)

            点赞5个,更新下一期!

  • 相关阅读:
    WebGIS----wenpack
    pyhanlp安装教程
    32位x86处理器
    mysql兼容微信表情
    软考 - 04 分布式缓存系统
    GUI编程--PyQt5--QMessageBox
    希尔排序算法
    点击化学TCO-PEG-SH|TCO-PEG-Thiol|反式环辛烯-聚乙二醇-巯基
    第14章_视图
    基于Springboot的校园求职招聘系统(有报告)。Javaee项目,springboot项目。
  • 原文地址:https://blog.csdn.net/ceshyong/article/details/126211832