C++求最小公倍数和最大公约数问题

来源:互联网 发布:c语言函数声明格式 编辑:程序博客网 时间:2024/04/30 14:12

问题描述如下(这是蓝桥杯的试题):
这道题的解答就是求三个数(假设为x,y,z)的最小公倍数,通过转化,这个最小公倍数可以转化成x*y*z÷最大公约数(x,y)÷最大公约数(x*y,z);所以问题的解答就变成了如何求最大公约数的问题上了。
而求最大公约数的最直接方法是欧几里得法,简单说就是(a,b)两个数的最大公约数等于(b,a%b)%为取余运算符。举个例子(42,24)=(24,18)=(18,6)=(6,0),所以最大公约数就是6;通过迭代就能简单求解。(这里要保证第一个数大于第二个数,若不满足,则将两个数的位置颠倒,如(0,6)=(6,0))
但是取余的开销还是蛮大的,另一种做法是相减,即(a,b)=(b,a-b),此处跟上面一样,假设a>b,若小于则两个数颠倒位置。但是减法的坏处是操作次数太多,比如求(100000,1)这种要操作很多很多次。那有没有又避免取余开销,又减少操作次数的呢,那就是将两种操作结合起来啦。
假设p是一个素数,注意是素数。b=p*n.则(a,b)=(a,n)(这里假设p不能被a整除),而我们知道2是一个最小素数,而且对2取余,实际可用通过位操作实现,开销很小。那如果p可以被a整除呢,假设a=p*m,b=p*n,则(a,b)=p*(m,n).所以写成的程序如下:

#include<iostream>using namespace std;int Fun(int a,int b){    if(b==0){        return a;    }    if(a<b)        return Fun(b,a);    if(a&1){        if(b&1)            return Fun(b,a-b);        else            return Fun(a,b>>1);    }    else{        if(b&1)            return Fun(a>>1,b);        else            return 2*Fun(a>>1,b>>1) ;    }} int main(){    int x,y,z;    int result=0;    while(cin>>x>>y>>z){        int a=Fun(x,y);        int b=Fun(x*y,z);        result=x*y*z/a/b;        cout<<result<<endl;     }     return 0; } 

代码风格比较丑,大家将就看看,还有上面欧几里得法之类的证明大家可以百度,或者自行证明,并不难。

0 0
原创粉丝点击