辗转相除法

辗转相除法、更相减损术(九章算术) 还是有点迷糊,

穿精又带淫゛_ 提交于 2020-04-07 07:27:12
首先重点无论式辗转相除法还是更相减损术,最重要的原理是:两个整数的最大公约数等于其中较小的数和两数的差的最大公约数 你可以这么理解, C=(A,B) ,C为A,B的最大公约数;即A,B都有公因数C,那么A-B也有公因数C, A%C=0; B%C=0; A%C-B%C=(A-B)%C=0 假设有两个数x和y,存在一个最大公约数z=(x,y),即x和y都有公因数z, 那么x一定能被z整除,y也一定能被z整除,所以x和y的线性组合mx±ny也一定能被z整除。(m和n可取任意整数) 对于辗转相除法来说,思路就是:若x>y,设x/y=n余c,则x能表示成x=ny+c的形式,将ny移到左边就是x-ny=c,由于一般形式的mx±ny能被z整除,所以等号左边的x-ny(作为mx±ny的一个特例)就能被z整除,即x除y的余数c也能被z整除。一直下操作, 最后就是更相减损术是拿来相减,而辗转相除是取余;当两个数很接近的时候前者算法效率高,两个数差距很大的时候后者效率高! 来源: https://www.cnblogs.com/Left-Behind/p/7554000.html

辗转相除法与更相减损术

大兔子大兔子 提交于 2020-04-07 07:26:45
          已知a、b求a与b的最大公因数与最小公倍数? 先说最大公因数   我们先把a、b改写成多个素数的幂相乘。比如a=36和b=54,那么a=2^2*3^2,b=2^1*3^3。根据定义最大公因数就是取a、b分解出的相同素数的最小指数相乘,即2^1*3^2=18。   辗转相除法就是用a、b中的大数对小数取余,再把余数和小数中的较小数取余,一直这样做,直到刚好整除,余数为0。比如36与54,先算54%36=18,再算36%18=0,结束,这里的18即为所求。  int gcd(int x,int y) { if(x%y==0) return y; else return zhanzhuan(y,x%y); }   然后是更相减损术。一种实现是把a、b中的大数减小数,然后把小数与差中的大数减小数,直到减到减数和差一样,此时的差即为所求。   比如36与54,先算54-36=18,再算36-18=18,此时18=18,18就是最大公因数了。 int gcd(int a,int b) { while(a!=b) { if(a>b)a=a-b; if(a<b)b=b-a; } return a; } 以上两种算法复杂度略玄学,有时快有时慢的…… 这里还有一种更相减损术的代码,复杂度是log级别的。 int gcd(int a,int b) { int F=1; while(a

更相减损法和辗转相除法(GCD)求最小公倍数和最大公约数

佐手、 提交于 2020-04-07 07:26:14
更相减损法和辗转相除法(GCD)求最小公倍数和最大公约数 标签(空格分隔): 算法 算法竞赛 这两种算法平时经常听到,听起来也很装逼,但是我老是忘了他们的原理,今天好好想想,写下来。 更相减损法 更相减损法最早起源于我国的《九章算术》,用于求两个数的最小公倍数。大意是给定两个数a,b,如果存在偶数,就将偶数以2;否则,就比较两数大小,用大数减小数,得到一个差;对差和剩下的那个小数重复该过程,直到两数相等,下一次相减结果为0,这时的数就是a和b的最大公约数。注意,去掉偶数除以2的步骤,也正确,但是加上这一步可能会让时间复杂度减少。 例如:15和12。15-12=3;12-3=9;9-3=6;6-3=3;3=3,跳出。则最大公因数是3。 算法的C/C++代码写法如下(循环实现): int gcdgxjs(int a,int b) { while (a!=b) { if (a if (a>b) a-=b; else b-=a; } return a; ) 辗转相除法 辗转相除法最早是由欧几里得发现的,也被用来求最大公约数。算法是这样的:给定两个数a,b,求a%b,如果余数非0,就继续用除数除以余数,重复该过程,直到除数为0。此时的被除数,就是最大公约数。 例如,42和12。42%12=6;12%6=0,6&0,此时的6即为最大公约数。 算法的C/C++代码写法如下(递归实现): int

辗转相除法证明

末鹿安然 提交于 2020-03-30 09:46:27
摘自百度百科: 设两数为a、b(b<a),用gcd(a,b)表示a,b的最大公约数,r=a mod b 为a除以b以后的余数,k为a除以b的商,即a÷b=k.......r。辗转相除法即是要证明gcd(a,b)=gcd(b,r)。 第一步:令c=gcd(a,b),则设a=mc,b=nc 第二步:根据前提可知r =a-kb=mc-knc=(m-kn)c 第三步:根据第二步结果可知c也是r的因数 第四步:可以断定m-kn与n互素【否则,可设m-kn=xd,n=yd,(d>1),则m=kn+xd=kyd+xd=(ky+x)d,则a=mc=(ky+x)dc,b=nc=ycd,故a与b最大公约数成为cd,而非c,与前面结论矛盾】 从而可知gcd(b,r)=c,继而gcd(a,b)=gcd(b,r)。 证毕。 来源: https://www.cnblogs.com/tanhehe/archive/2013/02/22/2921526.html

辗转相除法的证明

只愿长相守 提交于 2020-03-22 22:43:36
辗转相除法的证明   设两数为a、b(b<a),求它们最大公约数的步骤如下:用b除a,得a=bq+r(0≤r<b)(q是这个除法的商)。若r=0,则b是a和b的最大公约数。若r≠0,则继续考虑。   首先,应该明白的一点是任何 a 和 b 的公约数都是 r 的公约数。要想证明这一点,就要考虑把 r 写成 r=a-bq。现在,如果 a 和 b 有一个公约数 d,而且设 a=sd , b=td, 那么 r = sd-tdq = (s-tq)d。因为这个式子中,所有的数(包括 s-tq )都为整数,所以 r 可以被 d 整除。   对于所有的 d 的值,这都是正确的;所以 a 和 b 的最大公约数也是 b 和 r 的最大公约数。因此我们可以继续对 b 和 r 进行上述取余的运算。这个过程在有限的重复后,可以最终得到 r=0 的结果,我们也就得到了 a 和 b 的最大公约数。 来源: https://www.cnblogs.com/oiercc/p/7294315.html

欧几里得算法(辗转相除法)

邮差的信 提交于 2020-03-12 21:32:31
<!-- Euclid算法 --> 欧几里得算法即“辗转相除法”,用于求两个正整数的最大公约数(gcd)。 int gcd(int a, int b) { if(b == 0) return a; else return gcd(b, a % b); } 这是递归形式的代码,递归层数为4.785lgN + 1.6723,N是max(a, b),可见它递归不了多少层,不需要担心栈溢出的问题。 更精检的形式如下: int gcd(int a, int b) { return (b? gcd(b, a%b): a); } 我们使用这段代码的时候,需要保证a和b是非负整数,a、b同为0的情况要预先处理掉。事实上我们不需要管a和b的大小关系,代码在递归中,始终将大数放在前,我们即使将小数放在前也就是多一层递归而已。 另外还有一种仅通过位运算就可以达到目的的gcd: int gcd(int a, int b) { int t = 1, c, d; while(a != b) { if(a < b) swap(a, b); if(! (a & 1)) { a >>= 1; c = 1; } else c = 0; if(! (b & 1)) { b >>= 1; d = 1; } else d = 0; if(c && d) t <<= 1; else if(! c && ! d) a -= b

欧几里德算法(辗转相除法) 求最大公约数

元气小坏坏 提交于 2020-03-08 05:22:35
今天上课老师问"辗转相除法"又叫什么算法..居然没人知道..更居然的是..老师也忘了... 以前我貌似在VC的Samples里看到过这个算法, 似乎是叫欧几里德... 但也忘了是怎么辗转相除的.. 特此"百度知道"之: Euclid 欧几里德算法又称辗转相除法,用于计算两个整数a,b的最大公约数。其计算原理依赖于下面的定理: 定理:gcd(a,b) = gcd(b,a mod b) 证明: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)的公约数是一样的,其最大公约数也必然相等,得证。 欧几里德算法就是根据这个原理来做的,其算法用C++语言描述为: void swap(int & a, int & b) { int c = a; a = b; b = c; } int gcd(int a,int b) { if(0 == a ) { return b; } if( 0 == b) { return a; } if(a > b) { swap(a,b); } int c; for(c

算法:辗转相除法【欧几里德算法(Euclidean algorithm)】

青春壹個敷衍的年華 提交于 2020-03-08 05:22:10
1.来源 设两数为a、b(a>b),求a和b最大公约数(a,b)的步骤如下:用a除以b,得a÷b=q ......r1(0≤r1)。若r1=0,则(a,b)=b;若r1≠0,则再用b除以r1,得b÷r1=q ......r2 (0≤r2).若r2=0,则(a,b)=r1,若r2≠0,则继续用r1除以r2, ……如此下去,直到能整除为止。其最后一个为被除数的余数的除数即为(a, b)。 例如:a=25,b=15,a/b=1 ......10,b/10=1 ......5,10/5=2 .......0,最后一个为被除数余数的除数就是5,5就是所求最大公约数。 2.原理 3.算法 自然语言描述 用辗转相除法确定两个正整数 a 和 b(a≥b) 的最大公因数gcd(a,b): 当a mod b=0 时gcd(a,b)=b,否则 gcd(a,b) = gcd(b,a mod b) 递归或循环运算得出结果 /** * * @return int * @tags @param m * @tags @param n * @tags @return * @todo 【方法二】利用辗除法 */ public static int gcd(int m, int n) { while (true) { if ((m = m % n) == 0) return n; if ((n = n % m) ==

辗转相除法求最大公约数和最小公倍数分析

孤街醉人 提交于 2020-01-24 10:28:46
求最大公约数和最小公倍数 程序分析: (1)最小公倍数=输入的两个数之积除于它们的最大公约数,关键是求出最大公约数; (2)求最大公约数用辗转相除法(又名欧几里德算法) 辗转相除法: #include<stdio.h> int main() { int a,b,c; int raw_a,raw_b; scanf("%d %d",&a,&b); raw_a=a;raw_b=b; c=a%b; while (c!=0) { a=b;b=c; c=a%b; } printf("a与b的最大公约数是:%d\n",b); printf("a与b的最小公倍数是:%d\n",raw_a*raw_b/b); return 0; } 12 56 a与b的最大公约数是:4 a与b的最小公倍数是:168 具体步骤: #include<stdio.h> int main() { int a,b,c; int raw_a,raw_b; scanf("%d %d",&a,&b); raw_a=a;raw_b=b; c=a%b; printf("%d = %d * %d + %d\n",a,a/b,b,a%b); while (c!=0) { a=b;b=c; c=a%b; printf("%d = %d * %d + %d\n",a,a/b,b,a%b); } printf("\n"); printf(

求最大公约数——辗转相除法

蓝咒 提交于 2020-01-21 22:25:09
求最大公约数——辗转相除法 设求a和b的最大公约数c 则可看做边长分别为a和b的矩形,可恰好被边长为c的正方形无缝隙填满 方法:不断地用长边除以短边取余数,直到长边与短边相等,即为所求正方形 solve(a,b)=solve(b,a%b)=…… ……=solve(c,0) 代码: int solve ( int a , int b ) { if ( b == 0 ) return a ; else return solve ( b , a % b ) ; } 例题: 求线段上格点的个数 给定平面上的两个格点P1=(x1,y1)P2=(x2,y2),线段P1P2上,除P1和P2以外一共有几个点。 示例: P1=(3,9) P2=(7,1) 则求出7-3和9-1的最小公倍数为solve(8,4) 小矩形的边长为分别为8/solve(8,4)和4/solve(8,4) # include "stdio.h" # include "stdlib.h" int x1 , y1 ; int x2 , y2 ; int max ( int a , int b ) { return a > b ? a : b ; } int min ( int a , int b ) { return a > b ? b : a ; } int solve ( int a , int b ) { if ( b =