对于数论的研究,大家最早接触的应该就是著名的欧几里得算法了吧,也就是gcd算法,它的功能是求出两个数a,b的最大公约数,其实也就是我们经常说的的辗转相除法,关于它的证明。有很多方法。
下面我就介绍其中一种首先我们假设a和b的最大公约数是x;
那么就有a=k1x;b=k2x;我们保证b是较大的部分就可以的得出一个结论gcd(a,b)=gcd(a,(k2-k1)x)=gcd(a,b-a);
那么我们就可以保证在b小于a之前,我们可以减尽可能多的a来缩小数据规模,所以我们可以得到gcd(a,b)=gcd(a,b%a);直到出现0时的到最终答案a
用代码实现也很简单
int gcd(int a,int b)
{
return b==0?a;gcd(b,a%b);
}
它的复杂的是log(n)级别的(具体证明可以参考斐波那契的幂次递增)
说完了gcd算法,不得不提的就是最小公倍数算法lcm了
其实也很简单
我们先假设一个gcd(a,b)=x;
然后一定有a=k1x,b=k2x且k1,k2互质那么我们可以得到 lcm(a,b)=k1k2x
我们将ab相乘发现一个式子形如 lcm(a,b)gcd(a,b)=ab;至此我们就得到了lcm的log级求法,需要注意的是,为了防止数据范围过大,我们一般采用a/gcd(a,b)b来计算
而不是先算ab的方式