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

    xiaoxiao2021-03-25  69

    这道题的解答就是求三个数(假设为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; }

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

    转载请注明原文地址: https://ju.6miu.com/read-34463.html

    最新回复(0)