求最小公约数,最容易想到的是欧几里得算法,这个算法也是比较容易理解的,效率也是很不错的。也叫做辗转相除法。

对任意两个数a,b(a>b),d=gcd(a,b),如果b不为零,那么gcd(a,b)=gcd(b,a%b)

证明: 令 r=a%b,即存在k,使得 a=b*k+r,那么r=a-b*k;显然r>=0,  r%d=((a%d)-(b*k)%d)%d,因为a%d=b%d=0,所以r%d=0;

因此求gcd(a,b)可以转移到求gcd(b,a%b),那么这就是个递归过程了,那什么时候递归结束呢,想一下,a,b不能为零,则可以把当b为零,作为递归的结束(当然还可以以其它结束条件),这就是求最大公约数的方法可以以其它结束条件),这就是求最大公约数的方法。

欧几里得递归版:

int gcd(int a,int b)
{if(b==0) return a;else return gcd(b,a%b);
}

非递归版:

int gcd(int a,int b)//euclid
{int r;while(b!=0){r=a%b;a=b;b=r;}return a;
}

Stein算法

欧几里德算法是计算两个数最大公约数的传统算法,他无论从理论还是从效率上都是很好的。但是他有一个致命的缺陷,这个缺陷只有在大素数时才会显现出来。
硬件平台,一般整数最多也就是64位,对于这样的整数,计算两个数之间的模是很简单的。对于字长为32位的平台,计算两个不超过32位的整数的模,只需要一个指令周期,而计算64位以下的整数模,也不过几个周期而已。但是对于更大的素数,这样的计算过程就不得不由用户来设计,为了计算两个超过 64位的整数的模,用户也许不得不采用类似于多位数除法手算过程中的试商法,这个过程不但复杂,而且消耗了很多CPU时间。对于现代密码算法,要求计算 128位以上的素数的情况比比皆是,设计这样的程序迫切希望能够抛弃除法和取模。
Stein算法由J. Stein于1961年提出,这个方法也是计算两个数的最大公约数。和欧几里德算法不同的是,Stein算法只有整数的移位和加减法,这对于程序设计者是一个福音。
为了说明Stein算法的正确性,首先必须注意到以下结论: 
gcd(a,a) = a,也就是一个数和他自身的公约数是其自身 
gcd(ka,kb) = k gcd(a,b),也就是最大公约数运算和倍乘运算可以交换,特殊的,当k=2时,说明两个偶数的最大公约数必然能被2整除 
当k不能整除b,gcd(ka,b)=gcd(a,b),也就是约掉两个数中只有其中一个含有的因子不影响最大公约数。特殊地,当k=2时,说明计算一个偶数和一个奇数的最大公约数时,可以先将偶数除以2。

算法步骤:
    1、如果A=0,B是最大公约数,算法结束
  2、如果B=0,A是最大公约数,算法结束
  3、设置A1=A、B1=B和C1=1
  4、如果An和Bn都是偶数,则An+1=An/2,Bn+1=Bn/2,Cn+1=Cn*2(注意,乘2只要把整数左移一位即可,除2只要把整数右移一位即可)
  5、如果An是偶数,Bn不是偶数,则An+1=An/2,Bn+1=Bn,Cn+1=Cn(很显然啦,2不是奇数的约数)
  6、如果Bn是偶数,An不是偶数,则Bn+1=Bn/2,An+1=An,Cn+1=Cn(很显然啦,2不是奇数的约数)
  7、如果An和Bn都不是偶数,则An+1=|An-Bn|/2,Bn+1=min(An,Bn),Cn+1=Cn
  8、n加1,转1

比较好理解吧,实现起来也比较简单,效率也不比员算法差;

下面是实现的代码:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
using namespace std;
int stein(int a,int b)
{if(a==0) return b;if(b==0) return a;if(a%2==0 && b%2==0) return 2*stein(a>>1,b>>1);else if(a%2==0)   return stein(a>>1,b);else if(b%2==0)   return stein(a,b>>1);else return stein(abs(a-b),min(a,b));
}
int main()
{int a,b;scanf("%d%d",&a,&b);printf("%d\n",stein(a,b));
}

最小公约数(欧几里得算法stein算法)相关推荐

  1. php 辗转相除法,手撸golang 基本数据结构与算法 最大公约数 欧几里得算法/辗转相除法...

    手撸golang 基本数据结构与算法 最大公约数 欧几里得算法/辗转相除法 缘起 最近阅读<>([日]石田保辉:宫崎修一) 本系列笔记拟采用golang练习之 欧几里得算法欧几里得算法(又 ...

  2. 求最大公约数与最小公倍数 (辗转相除法+更相减损法+Stein算法)

    辗转相除法与更相减损法对比: (1)两者都是求最大公因数的方法,计算上辗转相除法以除法为主,更相减损术以减法为主,计算次数上辗转相除法计算次数相对较少,特别当两个数字大小区别较大时计算次数的区别较明显 ...

  3. Java实现算法导论中最大公约数欧几里得算法

    最大公约数的欧几里得算法,代码如下: package cn.ansj;public class GCD {public static void main(String args[]) { GCD g ...

  4. 求最大公约数欧几里得算法原理证明

      辗转相除法, 又名欧几里德算法(Euclidean algorithm),是求最大公约数的一种方法.它的具体做法是:用较大数除以较小数,再用出现的余数(第一余数)去除除数,再用出现的余数(第二余数 ...

  5. 求最大公约数——欧几里得算法(JAVA)

    欧几里得算法 问题描述:给出两个数m,n,求解这两个数的最大公因数 由于算法比较简单,这里不再赘述,我做的这个算法是默认了m>n,如果是对于任意两个数来说的话,我们这里还需要一个比较大小. pu ...

  6. Python:三种方法计算最大公约数和最小公倍数(欧几里德法、穷举法、stein算法)

    Python:三种方法计算最大公约数和最小公倍数 1.穷举法 2.欧几里德法 3.Stein算法 题目:求取任意两个非负数(至多一个数为0)的最大公约数和最小公倍数: 参考资料:Python解决求最大 ...

  7. 辗转相除法、更相减损法、Stein算法

    最大公约数和最小公倍数求解,常用的方法是短除法进行因式分解,然后最大公约数是所有公共因子的乘积,最小公倍数是所有因子的乘积. 本质上求最小公倍数就是求最大公倍数:x=m*a, y=m*b:m是最大公约 ...

  8. 密码学基础算法(一)基于整数的欧几里得算法和扩展欧几里得算法

    图片来源: 随便谷歌的一个图片 图片地址: https://jason-chen-1992.weebly.com/uploads/1/0/8/5/108557741/euclidean_3_orig. ...

  9. 扩展欧几里得算法、乘法逆元与中国剩余定理

    文章目录 前言 定义.定理和部分证明 整除 定义 定理 定理的证明 同余 定义 同余的性质 同余的运算律 运算律的证明 扩展欧几里得算法 代码模板 算法详解 乘法逆元 求解逆元 乘法逆元的作用 中国剩 ...

最新文章

  1. 为什么说BCH是最安全的数字货币之一?
  2. hadoop2.4.1+hbase0.98.3实现的分布式网盘系统初步(已开源)
  3. C与C++在形参的一点小区别
  4. Servlet请求和响应总结
  5. 取地址符和解引用符的区别_(&)和解引用(*)运算符的地址以及C中的指针...
  6. 关于产品经理如何准备面试,我有三点想法
  7. java程序设计经典课堂讲课_Java程序设计与开发经典课堂
  8. 个人知识整理(javascript篇初识)
  9. Spring mvc+ maven + MyBatis + Oracle + IDEA 项目搭建 - framework 进阶中(一)
  10. ad logon hour
  11. 小腹下面是什么部位_产后新妈妈去掉大肚腩,恢复平坦小腹,不妨试试这4个动作...
  12. C++解析char *p与char p[]
  13. vs C++实现Socket通信、添加ws2_32.lib 静态链接库
  14. 解决Win10任务栏不显示电池电量的问题
  15. java中的原型模式_原型模式(原型设计模式)详解
  16. 给定两个字符串 s 和 t,它们只包含小写字母。 字符串 t 由字符串 s 随机重排,然后在随机位置添加一个字母。 请找出在 t 中被添加的字母
  17. css字体毛边属性设置
  18. MS PROJECT 下载
  19. 官方纯净版windows10教育版安装密钥极其下载地址
  20. 使用IDEA插件反编译jar包文件

热门文章

  1. 可以级联的以太网远程IO模块的优点与具体的适用场景
  2. python之print(f“ “)用法
  3. 【转载】第一次有人把 5G 讲的这么简单明了
  4. Android开发UI之隐藏导航栏
  5. 2021年茶艺师(初级)证考试及茶艺师(初级)模拟考试题
  6. Python+Selenium练习篇之25-鼠标右键
  7. 嵌入式linux下应用程序,嵌入式Linux应用程序开发详解(完整下载)
  8. Android富文本开发,从0到1!
  9. Linux系统进程停止的方法
  10. Mac必备神器Homebrew