gcd(gong chan dang)(greatest common divisor) 最大公约数,指两个整数全部公共约数中最大的。ios
首先先上结论,求最大公约数,咱们能够经过递归gcd(a,b)=gcd(b,a%b),gcd(a,0)=a计算,复杂度是logngit
很明显,这个伟大的结论gcd(a,b)=gcd(b,a%b),就是著名的欧几里得公式。spa
那么怎么证,其实还挺简单的。咱们把证实分为两步骤:code
一、证实gcd(a,b)是b,a%b的一个公约数blog
二、证实这个公约数是最大的。递归
一、咱们设gcd(a,b)=d,再令a=k1*d,b=k2*d.get
咱们再设,a=k*b+c(也就是a除以b商k余c),那么c就是余数,也就是a%b.string
讲上面那个式子移项,获得c=a-k*b,而后再把a=k1*d,b=k2*d,这两个式子里的a、b带入式子,获得:it
c=k1*d-k*k2*d,在提取公因数d,获得c=(k1-k*k2)*d.这样就说明,c,也就是a%b有d这个约数,由于开始咱们设b也有d这个约数,因此gcd(a,b)是b,a%b的一个公约数。io
二、如今知道了它是一个公约数,那么怎么证它是最大的?(其实感性分析,a%b都变小了,公约数不可能更大呀!)
可是术学是一门严谨的学科,咱们要严谨证实。咱们知道,c(a%b)=(k1-k*k2)*d,b=k2*d,咱们只须要证实k1-k*k二、k2互质就行了。
这里能够用到反证法:咱们假设k1-k*k2=q*t,k2=p*t,而且t>1(也就是那两个不互质)。
咱们将前面那个式子移项,获得k1=q*t+k*k2,再把这个k1代到最开始的a=k1*d,获得a=(q*t+k*k2)*d,再利用乘法分配律,获得:
a=q*t*d+k*k2*d,咱们这时发现,k2*d不就是最开始的b吗?,将其带入,获得:a=q*t*d+b*d.
这时,咱们再把k2=p*t代入开始的b=k2*d,获得b=p*t*d,再把这个式子代到a=q*t*d+b*d.获得了:a=q*t*d+p*t*d.提取公因数:a=(q+p)*t*d
如今,再和b=p*t*d比较,发现他们的最大公因数变成了t*d和开始矛盾,因此假设不成立,反证成功!
好吧,仍是贴一下求最大公约数的代码吧
#include <iostream> #include <cstdlib> #include <cstring> #include <algorithm> #define REP(i,k,n) for(int i=k;i<=n;i++) #define in(a) a=read() using namespace std; inline int read(){ int x=0,f=1; char ch=getchar(); for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1; for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0'; return x*f; } inline int gcd(int a,int b){ if(b==0) return a; return gcd(b,a%b); } int main(){ int a,b; in(a),in(b); cout<<gcd(a,b); }