1:欧几里得算法,既辗转相除法。用于计算正整数a,b的最大公约数。举个例子,简单明了:
12/8==1.....4
8/4==2......0
4/0==0 ,除数为0,终止,被除数为答案:4
除数和余数反复做%运算,其实和/没什么关系了,直接看%就可以了,所以有递归代码:
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a; }
最小公倍数求解:a,b的最小公倍数等于a,b的乘积除以a,b的最大公约数:
cout<<x/gcd(x,y)*y<<endl;
2:拓展欧几里得算法:参考自:https://blog.csdn.net/destiny1507/article/details/81750874,感谢大佬!
首先有贝祖定理:a,b为整数,那么一定存在x,y使得a*x+b*y==gcd(a,b)。也可以说,a*x+b*y==m,那么m一定是gcd(a,b)的若干倍,可以用来判断方程是否有解。如何求x,y?这就是拓展欧几里得可以解决的一个问题了。
如果辗转相除法到达了最底层:即a%b==0,此时a*x+b*y==gcd(a,b),x==1,y==0。此时的a,b已经不是初始的a,b了,要想得到初始a,b的x,y,需要递归到最底层再一层层往上推各个层次的x,y,直到第一层。递归算法中,是先得到下一个状态值。
所以算a,b的x,y,假设下一层b,a%b得到了gcd,这个下一层是满足:b*x1+a%b*y1==gcd。对于a%b,有:a%b=a-(a/b)*b。所以原式为:
b*x1+(a-a/b*b)*y1=a*y1+b*(x1-a/b*y1)。
所以:x==y1,y==(x1-a/b*y1)。y1,x1均来源于下一层,所以通过递归先得到下一层,然后根据式子推出当前一层,直到得到原a,b的x,y来。
ll x,y,a,b; void exgcd(ll a, ll b) { if(b==0) { x=1; y=0; return ; } exgcd(b,a%b); ll t=x; x=y; y=t-a/b*y; return ; }