最大公约数

•最大公约数:两个不同时为0的a与b的公约数中最大的称为最大公约数,记为gcd(a,b)
•最大公约数的基本性质:
•gcd(a,b)=gcd(b,a)
•gcd(a,b)=gcd(-a,b)
•gcd(a,b)=gcd(|a|,|b|)
•gcd(a,0)=|a|
•gcd(a,k*a)=|a|
•gcd(a*n,b*n)=n*gcd(a,b)
•若d|a且d|b,则d|gcd(a,b)
•若n|ab且gcd(a,n)=1,则n|b
•若gcd(a,p)=1且gcd(b,p)=1,则gcd(a*b,p)=1
问题一:给定a,b,计算gcd(a,b)
•方法1:枚举法
  从min(a,b)到1枚举x,并判断x是否能同时整除a和b,如果可以则输出x退出循环。时间复杂度为O(min(a,b))。
•方法2:分解质因子
  对a,b分别分解质因子,$a={p_1}^{x_1}*{p_2}^{x_2}*...{p_n}^{x_n}$,$b={p_1}^{y_1}*{p_2}^{y_2}*...{p_n}^{y_n}$,其中xi,yi>=0且不会同时为0(1<=i<=n),则    
    gcd(a,b)=${p_1}^{min({x_1},{y_1})}$*${p_2}^{min({x_2},{y_2})}$*...${p_n}^{min({x_n},{y_n})}$。
  如何分解a和b?
  以a为例,根据唯一因子分解定理,从2开始依次枚举因子i,如果i能整除a,则把i从a中分解出去,再考虑i+1。如果a是合数,则一定存在a=b*c(b<=c,b!=1,c!=n),则有b*b<=b*c=a,b<=$sqrt a$。即如果a是合数则在2到$sqrt a$内一定存在质因子,循环i执行到i*i>a为止,如果a不等于1,则a也是素因子。
•方法3:欧几里得算法
•定理:gcd(a,b)=gcd(b,a mod b)
••证明(1):
  设gcd(a,b)=p,则有a=a'*p,b=b'*p,gcd(a',b')=1
  a mod b=a-$a over b$*b=p*(a'-$a over b$*b')
  gcd(b,a mod b)=gcd(b'*p,p*(a'-$a over b$*b'))=p*gcd(b',a'-$a over b$*b')
  证明gcd(b',a'-$a over b$*b')=1:
  反证法,如果gcd(b',a'-$a over b$*b')=t(t>1)设b'=b''*t,a'-$a over b$*b'=c'*t,则有a'=$aover b$*b''*t+c'*t=t*($a over b$*b''+c')$显然t|b',t|a',与gcd(a',b')=1相矛盾
  所以gcd(b,a mod b)=p=gcd(a,b)
••证明(2):
  a可以表示成a = kb + r,则r = a mod b
  假设d是(a,b)的一个公约数,则有d|a, d|b,而r = a - kb,因此d|r
  因此d是(b,a mod b)的公约数
  假设d是(b,a mod b)的公约数,则d|b,d|r,但是a = kb +r
  因此d是(a,b)的公约数
  因此(a,b)和(b,a mod b)的公约数是一样的,其最大公约数也必然相等,得证
••时间复杂度分析(1):
  根据(a,b)=>(b,a mod b),
  设a>b:
  ①当a>=2*b时,b<=a/2,规模至少缩小一半;
  ②当a<2*b时,a mod b<a/2
  时间复杂度为O($log_N$)
••时间复杂度分析(2):
•••定理:斐波那契数列f(0)=0,f(1)=1,f(n)=f(n-1)+f(n-2)(n>=2)。a>b>=1且Euclid(a,b)执行了k(k>=1)次递归调用,则a>=f(k+2),b>=f(k+1)
••••证明:数学归纳法
     ①当k=1时,b>=f(2)=1,因a>b,所以a>=2=f(3),成立。
     ②假设当k=x时成立,即满足a>=f(x+2),b>=f(x+1),当k=x+1时:
     第一次递归调用(a,b)变成(b,a mod b),由于从(b,a mod b)开始递归调用了x次完成,所以满足:
     b>=f(x+2),a mod b>=f(x+1)
     又因为a>b,所以a>=b+a mod b>=f(x+2)+f(x+1)=f(x+3)
     即当k=x+1时,a>=f(x+3),b>=f(x+2),同样满足结论!
     ③得证!
••••计算f(n)的公式:参见附录
••••时间复杂度O(${log_phi}^{{sqrt 5 *b} over {gcd(a,b)}}$    )
•方法4:二进制法
  ①a<b时,gcd(a,b)=gcd(b,a)
  ②a=b时,gcd(a,b)=a
  ③a,b同为偶数时,gcd(a,b)=gcd(a/2,b/2)
  ④a为偶数,b为奇数时,gcd(a,b)=gcd(a/2,b) 
  ⑤a为奇数,b为偶数时,gcd(a,b)=gcd(a,b/2)
  ⑥a,b同为奇数时,gcd(a,b)=gcd(a-b,b)
  ⑦适合求高精度数的最大公约数
 
附录A:
http://www.cnblogs.com/frog112111/archive/2012/08/19/2646012.html
附录B:
 方法二:
 1      void Decompose()
 2      {
 3          for(int x=2;x*x<=min(a,b);x++)
 4          {
 5              while (a % x==0 && b % x==0){a/=x;b/=x;ans*=x;}
 6              while (a % x==0)a/=x;
 7              while (b % x==0)b/=x;
 8          } 
 9          if (a % b==0)ans*=b;
10          else if (b % a==0)ans*=a;
11          printf("%d",ans);
12      }
方法三
1 int gcd(int a,int b) { return b ? gcd(b,a%b) : a;}
方法四
1 int Gcd(int m,int n){
2     if (m==n) return m;
3     if (m<n) return Gcd(n,m);
4     if (m & 1==0) return (n & 1==0)? 2*Gcd(m/2,n/2):Gcd(m/2,n);
5     return (n & 1==0)? Gcd(m,n/2): Gcd(n,m-n);
6 }

 附录C

计算斐波那契数列的方法

 
原文地址:https://www.cnblogs.com/hjj1871984569/p/5931198.html