[编程之美]最大公约数(Greatest Common Divisor)

View Code
 1 //辗转相除法
2 //设k=x/y,b=x%y,则x=ky+b
3 //求x和y的最大公约数,也就是求y和b的最大公约数
4 int gcd(int x,int y)
5 {
6 while(y)
7 {
8 int b=x%y;
9 x=y;
10 y=b;
11 }
12 return x;
13 }

 

View Code
 1 int gcd(int x,int y)
2 {
3 while(x!=y)
4 {
5 if(x>y)
6 x=x-y;
7 else
8 y=y-x;
9 }
10 return x;
11 }

 

View Code
 1 //如果y=k*y1 x=k*x1,则gcd(x,y)=k*gcd(x1,y1)
2 //如果x=p*x1(p是素数),并且y%p!=0,那么gcd(x,y)=gcd(p*x1,y)=gcd(x1,y)
3 //因为2是素数,同时对于二进制表示的大整数而言,可以很容易的除以2和乘以2(移位),所以取p=2
4 //如果x,y均为偶数,则gcd(x,y)=2*gcd(x>>1,y>>1)
5 //如果x为偶数,y为奇数,则gcd(x,y)=gcd(x>>1,y)
6 //如果x为奇数,y为偶数,则gcd(x,y)=gcd(x,y>>1)
7 //如果x,y均为奇数,则gcd(x,y)=gcd(x-y,y)
8
9 int gcd(int x,int y)
10 {
11 int k=0;
12 while(x!=y)
13 {
14 if(x%2==0)
15 {
16 if(y%2==0)
17 {
18 x=x>>1;
19 y=y>>1;
20 ++k;
21 }
22 else
23 {
24 x=x>>1;
25 }
26 }
27 else
28 {
29 if(y%2==0)
30 {
31 y=y>>1;
32 }
33 else
34 {
35 if(x>y)
36 x=x-y;
37 else
38 y=y-x;
39 }
40 }
41 }
42 return x<<k;
43 }

 

最小公倍数(Least Common Multiple):两个数的乘积再除以最大公约数即为两个数的最小公倍数。

 

最大公约数的一些定理:

如果a和b是不都为0的任意整数,则gcd(a,b)是a与b的线性组合集合{ax+by:x,y属于整数}中的最小正元素。

对任意整数a与b,如果d | a并且d | b,则d | gcd(a,b)。

对所有整数a和b以及任意非负整数n,gcd(an,bn)=n*gcd(a,b)。

对所有正整数n,a和b,如果n | ab并且gcd(a,n)=1,则n | b。

一个扩展的求最大公约数的欧几里得算法。可以计算d=gcd(a,b)=ax+by中的三元组(d,x,y)

1 EXTENDED-EUCLID(a,b)
2     if(b==0)
3         return (a,1,0)
4     (d',x',y')=EXTENDED-EUCLID(b,a mod b)
5     //根据d=d'即可推导
6     (d,x,y)=(d',y',x'-ceil(a/b)*y')
7     return (d,x,y)

欧几里得算法的递归调用次数为O(lgb) (a>b>0)

 

求解模线性方程

a*x=b (mod n),其中a和n是任意正整数,b为任意整数

1 MODULAR-LINEAR-EQUATION-SOLVER(a,b,n)
2      (d,x',y')=EXTENDED-EUCLID(a,n)
3      if(d整除b)
4           x0=x'*(b/d) mod n
5           for(i=0;i<d;++i)
6               print (x0+i*(n/d)) mod n
7     else
8          no solutions
posted @ 2012-03-28 16:35  Cavia  阅读(718)  评论(0编辑  收藏  举报