【数论】欧几里得算法

一、具体内容:

  内容很简单,只有一个式子:gcd(a,b)=gcd(b,a%b),可以用来求a与b的最大公因数

二、不严谨的证明:

  首先不妨设a>b,r=a%b且r≠0,得到a=kb+r(a,b,r,k均为正整数)

  设d是a和b的一个公因数,即d|a,d|b

  已知r=a-kb,将两边同除d,即r/d=a/d-kb/d,a,b均是d的倍数,

  因此a/d与kb/d均为整数,可得r/d为整数,即d|(a%b)

  因此d也是b,a mod b的公约数,因(a,b)与(b,a%b)的公因数相等,

  所以gcd(a,b)=gcd(b,a%b),得证

三、代码实现

  我们很容易就可以看出gcd(a,b)的子问题结构,接下来考虑边界,当a%b==0,即a时b的倍数时,显而易见gcd(a,b)=b

#include<bits/stdc++.h>
using namespace std;
int x,y;
int GCD(int a,int b)
{
    if(!(a%b)) return b;
    return GCD(b,a%b);
}
//可以用"?"运算符将函数压缩成这样
//int GCD(int a,int b){return a%b?GCD(b,a%b):b;}
int main()
{
    scanf("%d%d",&x,&y);
    printf("%d",GCD(x,y));
}

四、算法优化

  上述算法的时间已经相当优秀了,我们只能用位运算对常数进行优化

#include<bits/stdc++.h>
using namespace std;
int x,y;
int GCD(int a,int b)
{
    if(a==b) return a;
    if((a&1)&&(b&1)) return gcd(b,abs(a-b));
    else if((a&1)&&(!(b&1))) return gcd(a,b>>1);
    else if((!(a&1))&&(b&1)) return gcd(a>>1,b);
    else return gcd(a>>1,b>>1)<<1;
}
int main()
{
    scanf("%d%d",&x,&y);
    printf("%d",GCD(x,y));
}

 

posted @ 2022-07-18 11:24  正在加载90%  阅读(46)  评论(0编辑  收藏  举报