-
迭代版的 g c d gcd gcd算法
def gcd(a, b): while b != 0: tmp = a % b a = b b = tmp return a n1, n2 = map(int, input().split(" ")) print(gcd(n1, n2))
-
递归版本的egcd算法
def egcd(a, b, f1, f2, s1, s2): if b == 0: return f1, f2, a return egcd(b, a % b, s1, s2, f1 - a // b * s1, f2 - a // b * s2) n1, n2 = map(int, input().split(" ")) print(egcd(n1, n2, 1, 0, 0, 1))
-
begcd
由于这个比较难,我先找了bgcd算法,维基上的前提是
- g c d ( 0 , v ) = v gcd(0, v) = v gcd(0,v)=v, because everything divides zero, and v is the largest number that divides v. Similarly, g c d ( u , 0 ) = u gcd(u, 0) = u gcd(u,0)=u.
- g c d ( 2 u , 2 v ) = 2 ⋅ g c d ( u , v ) gcd(2u, 2v) = 2·gcd(u, v) gcd(2u,2v)=2⋅gcd(u,v)
- g c d ( 2 u , v ) = g c d ( u , v ) gcd(2u, v) = gcd(u, v) gcd(2u,v)=gcd(u,v), if v is odd ( 2 2 2 is not a common divisor). Similarly, g c d ( u , 2 v ) = g c d ( u , v ) gcd(u, 2v) = gcd(u, v) gcd(u,2v)=gcd(u,v) if u is odd.
- g c d ( u , v ) = g c d ( ∣ u − v ∣ , m i n ( u , v ) ) gcd(u, v) = gcd(|u − v|, min(u, v)) gcd(u,v)=gcd(∣u−v∣,min(u,v)), if u and v are both odd.
def begcd(a, b): if a == 0: return b if b == 0: return a shift = 0 while (a | b) & 1 == 0: shift += 1 a >>= 1 b >>= 1 while a & 1 == 0: a >>= 1 while b != 0: while b & 1 == 0: b >>= 1 if b > a: a, b = b, a a -= b return a << shift a = eval(input()) b = eval(input()) print(begcd(a, b))
-
begcd
#include<stdio.h> #include<stdlib.h> void swap(int* a,int* b){ int tmp=*a; *a=*b; *b=tmp; } //input:integer a b //output:gcd(a,b)=d and integer x y which satisfy ax+by=d int* begcd(int a,int b){ int r=a; int _r=b; int k=0; while(!(r&1) && !(_r&1)){ r>>=1; _r>>=1; k++;//if a b are even,gcd(a,b)=2^k*gcd(a>>k,b>>k) } int _a=r; int _b=_r; int x=1;int y=0;int _x=0;int _y=1;//initialize while(_r){ while(!(r&1)){//r is even,r' is odd.So a' is even,b' is odd r>>=1; if(!(x&1) && !(y&1)){ x>>=1;y>>=1;//when x,y,r are both even,we can reduce } else{//ab-ab=ab'*2^k+a'b*2^k=0,So ab'+a'b=0 x=(x+_b)>>1;//odd+odd=even y=(y-_a)>>1;//even+even=even } } while(!(_r&1)){//r'is even,so r is odd,b' is even,a' is odd _r>>=1; if((_x&_y)&1){ _x>>=1;_y>>=1; } else{ _x=(_x+_b)>>1; _y=(_y-_a)>>1; } } if(_r<r){ swap(&r,&_r);//move a row swap(&x,&_x); swap(&y,&_y); }//_r now greater than r _r-=r;_x-=x;_y-=y;//mod } int *res=(int*)malloc(sizeof(int)*3); res[0]=x;res[1]=y;res[2]=(r<<k); return res; } int main(){ int a,b; scanf("%d%d",&a,&b); int *tmp=begcd(a,b); printf("%d*%d+%d*%d=%d\n",a,tmp[0],b,tmp[1],tmp[2]); free(tmp); return 0; }
这个感觉太难了,我想了很久都想不出,就证明下它的正确行就好了。
首先有 a x 1 + b y 1 = d = a / 2 n ∗ x 1 + b / 2 n ∗ y 1 = 2 n ∗ d 1 ax_1+by_1=d=a/2^n*x_1+b/2^n*y_1=2^n*d_1 ax1+by1=d=a/2n∗x1+b/2n∗y1=2n∗d1,则第一个while循环正确,又想了好久还是想不出为什么,不管了。
-
定理 2.2 2.2 2.2Bézout定理的证明
构造集合 S = { a r + b s } S= \lbrace ar+bs\rbrace S={ar+bs},因为 S S S肯定不为空,所以根据良序定理,S中存在最小元素 d 0 d_0 d0,对于集合 S S S中任意元素 d d d,假设 d = d 0 ∗ x + y , d = a r 1 + b s 1 , d 0 = a r 2 + b s 2 d=d_0*x+y,d=ar_1+bs_1,d_0=ar_2+bs_2 d=d0∗x+y,d=ar1+bs1,d0=ar2+bs2,所以 a r 1 + b s 1 = x ∗ ( a r 2 + b s 2 ) + y , y = ( r 1 − x ∗ r 2 ) a + ( s 1 − x ∗ s 2 ) b ar_1+bs_1=x*(ar_2+bs_2)+y,y=(r_1-x*r_2)a+(s_1-x*s_2)b ar1+bs1=x∗(ar2+bs2)+y,y=(r1−x∗r2)a+(s1−x∗s2)b, y ∈ S y \in S y∈S,因为 d 0 d_0 d0是S中最小的元素,所以根据余数的定义, y = 0 y=0 y=0,对于S中的任意元素,都能整除 d 0 d_0 d0,所以 d 0 d_0 d0是a, b的公因数。
假设任意一个 a 与 b a与b a与b的公因数为d, a = d n 1 , b = d n 2 a=dn_1,b=dn_2 a=dn1,b=dn2, d 0 = d n 1 r 1 + d n 2 s 1 d_0=dn_1r_1+dn_2s_1 d0=dn1r1+dn2s1,于是 d 0 d_0 d0整除a与b的任意一个公因数,所以 d 0 d_0 d0为a与r的最大公因数,于是证明存在 r 1 , s 1 ∈ Z r_1,s_1 \in Z r1,s1∈Z使得 d 0 = a r 1 + b s 1 d_0=ar_1+bs_1 d0=ar1+bs1。
CINTA作业2
最新推荐文章于 2022-09-20 23:02:24 发布