证明最大公约数Stein算法(高精度算法)

 

   E:even 奇数  O:odd 偶数

(a,b)为(e,e),则gcd(a,b)=2*gcd(a/2,b/2)

(a,b)为(e,o),则gcd(a,b)=gcd(a/2,b)

(a,b)为(o,o)[a>=b],则gcd(a,b)=gcd(a,b-a)

 

证明:

I.若a=c*d b=c*e 则gcd(a,b)=c*gcd(d,e)

这里c=2。

证明:

对于第一个质数,c拥有该质数的个数为ci,d拥有该质数的个数为di,e拥有该质数的个数为ei,而a拥有该质数的个数为ci+di,b拥有该质数的个数为ci+ei。对于任何质数,都有min(ci+di,ci+ei)=ci+min(di,ei),所以gcd(a,b)=c*gcd(d,e)。

a=56,b=16,c=2,对于质数2, ai=2,bi=4,ci=1,di=1,ei=3,min(2,4)=1+min(1,3)。

 

II.若a=c*d,但gcd(c,b)=1,则gcd(a,b)=gcd(d,b)

这里c=2。

证明:

对于一个质数,c拥有该质数的个数为ci, d拥有该质数的个数为di,b拥有该质数的个数为bi,而a拥有该质数的个数为ci+di,其中min(ci,bi)=0。对于任何质数,都有min(ci+di,bi)= min(di,bi)(

ci=0,min(di,bi)=min(di,bi),成立;

bi=0,min(ci+di,0)=min(di,0),成立),

所以gcd(a,b)=gcd(d,b)。

 

III. gcd(a,b)=gcd(b,a-bx)

这里x=1

证明:

gcd(a,b)=d,gcd(b,a-bx)=e,则

d|a,d|b

d|a-bx

d|gcd(b,a-bx),即d|e

e|b,e|a-bx

e|bx+(a-bx),即e|a

e|gcd(a,b),即e|d

d=e。证毕。

(来自Jollwish方法)

 

各种情况分析:

1.(e,e):(x,y)->(x/2,y/2)->…->[(e,o)/(o,e)/(o,o)]

只在开头出现

2.(o,e):(x,y)->(x,y/2)->…->[(o,o)]

偶数不断除以2知道变为奇数

3.(o,o):(x,y)->(x,y-x) [(o,e)]

(o,o)操作一遍变为(o,e),所以出现次数出现次数较少

 

所以只在开头判断是否为(e,e);每次先判断是否为(o,e)再判断是否为(o,o)

 

设定(a,b)中a必须为奇数。则一开始若为(e,o),通过两数交换变为(o,e)。当(o,o)时,若a<=b,则(a,b)->(a,b-a);若a>b,则(a,b)->(b,a-b)。

 

Another Way:

(o,e)中的偶数不停除以2,直到变为奇数,变为(o,o);而(o,o)通过一次操作变为(o,e),重复操作,直到(o,e)中的偶数为0。

 这个方法速度更快一点点。

 

高精度的实现:

高精度加法,高精度减法,高精度除法(高除低,除以2的特殊情况:对于每一位,若为奇数则下一位加1,若为偶数无操作;然后该位除以2)

 

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 
 4 int main()
 5 {
 6     long a,b,v,c=1;
 7     scanf("%ld%ld",&a,&b);
 8     //two evens
 9     //(e,e)->(e,o)/(o,e)/(o,o)
10     while ((a & 1)==0 && (b & 1)==0)
11     {
12         a>>=1;
13         b>>=1;
14         c<<=1;
15     }
16     //(e,o)->(o,e)
17     if ((a & 1)==0 && (b & 1)==1)
18     {
19         v=a;
20         a=b;
21         b=v;
22     }
23     while (a!=0 && b!=0)
24     {
25         //odd on the left,even on the right
26         //(a,b)->(a,b/2)
27         if ((a & 1)+(b & 1)==1)
28             b>>=1;
29         //two odds
30         //(a,b)->(a,b-a)/(a-b,b)
31         else
32         {
33             //when a<=b , (a,b-a)
34             if (a<b)
35                 b-=a;
36             //when a>b , (b,a-b)
37             else
38             {
39                 //(a,b)->(a,a-b)
40                 b=a-b;
41                 //(a,a-b)->(b,a-b)
42                 a-=b;
43             }
44         }
45     }
46     printf("%ld
",(a+b)*c);
47     return 0;
48 }
 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 
 4 int main()
 5 {
 6     long a,b,v,c=1;
 7     scanf("%ld%ld",&a,&b);
 8     //two evens
 9     //(e,e)->(e,o)/(o,e)/(o,o)
10     while ((a & 1)==0 && (b & 1)==0)
11     {
12         a>>=1;
13         b>>=1;
14         c<<=1;
15     }
16     //(e,o)->(o,e)
17     if ((a & 1)==0 && (b & 1)==1)
18     {
19         v=a;
20         a=b;
21         b=v;
22     }
23     while (a!=0 && b!=0)
24     {
25         //(o,e) or (o,o)[first time]
26         //b不会变为0
27         while ((b & 1)==0)
28             b>>=1;
29         //(o,o)
30         //when a<=b , (a,b-a)
31         if (a<b)
32             b-=a;
33         //when a>b , (b,a-b)
34         else
35         {
36             //(a,b)->(a,a-b)
37             b=a-b;
38             //(a,a-b)->(b,a-b)
39             a-=b;
40         }
41     }
42     printf("%ld
",(a+b)*c);
43     return 0;
44 }
原文地址:https://www.cnblogs.com/cmyg/p/6623194.html