求最大公约数的三种算法

辗转相除法(即欧几里德算法)求两个数的最大公约数的步骤如下:
先用小的一个数除大的一个数,得第一个余数;
再用第一个余数除小的一个数,得第二个余数;
又用第二个余数除第一个余数,得第三个余数;
这样逐次用后一个数去除前一个余数,直到余数是0为止。那么,最后一个除数就是所求的最大公约数(如果最后的除数是1,那么原来的两个数是互质数)。

例如求1515和600的最大公约数,
第一次:用600除1515,商2余315;
第二次:用315除600,商1余285;
第三次:用285除315,商1余30;
第四次:用30除285,商9余15;
第五次:用15除30,商2余0。
1515和600的最大公约数是15。

辗转相除法是求两个数的最大公约数的方法。如果求几个数的最大公约数,可以先求两个数的最大公约数,再求这个最大公约数与第三个数的最大公约数。这样依次下去,直到最后一个数为止。最后所得的一个最大公约数,就是所求的几个数的最大公约数。


具体代码:


/*
some test samples
9999999 9452134
9876543 6543214
8765432 7894562

*/
#include <iostream>         
#include <math.h>
#include <time.h>
#define SIZE1 10000001
#define SIZE2 1000001
using namespace std;
bool prime[SIZE1];
long f[SIZE2];
long nhave[SIZE2],mhave[SIZE2];

//欧几里德算法以无可争议的时空优势取得了第一名
long Euclid(long m,long n){     //欧几里德解法
    long r;
    while(n!=0){
        r=m%n;
        m=n;
        n=r;
    }
    return m;
}
long Force(long m,long n){      //穷举暴力法
    long r;
    for(r=m<=n?m:n;;r--)
        if(m%r==0&&n%r==0)
            return r;
}
long GenPrime(long n){     //筛选法求素数
    long i,j,k,sq;
    sq=(long)sqrt(n);
    for(i=2,k=0;i<=n;i++)
        if(prime[i]==0){
            if(i<=sq)
                for(j=i*i;j<=n;j+=i)
                    prime[j]=1;
            f[k++]=i;
        }
    f[k]=0x7fffffff;
    return k;
}
long PrimeGcd(long m,long n){ //素数因子法
    long i,j,v,mn,gcd;
    mn=m<=n?m:n;
    for(i=0;f[i]<=mn;i++)
        nhave[i]=mhave[i]=0;
    for(i=0;f[i]<=mn;)
        if(m%f[i]==0)
            mhave[i]++,m/=f[i];
        else
            i++;
    for(i=0;f[i]<=mn;)
        if(n%f[i]==0)
            nhave[i]++,n/=f[i];
        else
            i++;
    for(i=0,gcd=1;f[i]<mn;i++){
        v=nhave[i]<=mhave[i]?nhave[i]:mhave[i];
        if(v!=0)
            for(j=0;j<v;j++)
            gcd*=f[i];
    }
    return  gcd;
}
int main(){
    long m,n,gcd,i,mx,all;
    clock_t start,finish;
    start=clock();
    all=GenPrime(SIZE1-1);
    finish=clock();
    cout<<start<<' '<<finish<<' '<<finish-start<<endl;      //筛选法求素数时间
    while(cin>>m>>n){
        start=clock();
        gcd=Euclid(m,n);
        finish=clock();
        cout<<"Euclid: "<<gcd<<' '<<start<<' '<<finish<<' '<<finish-start<<endl;//最大公约数,算法开始、结束时间,运行时间
       
        start=clock();
        gcd=Force(m,n);
        finish=clock();
        cout<<"Brute force: "<<gcd<<' '<<start<<' '<<finish<<' '<<finish-start<<endl;
       
        start=clock();
        gcd=PrimeGcd(m,n);
        finish=clock();
        cout<<"Middle school procedure: "<<gcd<<' '<<start<<' '<<finish<<' '<<finish-start<<endl;
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值