浅谈Stein算法求最大公约数(GCD)的原理及简单应用

一、Stein算法过程及其简单证明

1.一般步骤:

s1:当两数均为偶数时将其同时除以2至至少一数为奇数为止,记录除掉的所有公因数2的乘积k;

s2:如果仍有一数为偶数,连续除以2直至该数为奇数为止;

s3:用更相减损法(辗转相减法),即GCD(a,b)=GCD(a-b,b)求出两奇数的最大公约数d;

s4:原来两数的最大公约数即为d*k;

2.简单证明:

s1:即为求出两数为2的幂次方的最大公因数k;

s2:当化简后两数一奇一偶时,显然奇数是不含偶数因子的,那么另一化简后偶数的所有偶数因子都不可能为原来两数的最大公因数的因子;

s3:求出原来两数不为2的幂次方的最大公因数d;

s4:最大公因数即为2的幂次方的最大公因数k乘以不为2的幂次方的最大公因数d;

3.Stein算法的优点:

欧几里得算法在处理较小数字时优势是明显的,但对于大整数时,高精度的整除和取余运算就显得非常复杂,所以Stein算法的优点就在于只需要进行移位(位运算)和减法操作,相较于前两者来说便于书写;

4.相关位运算符的简单介绍:

(1)按位与(&):

a&x为对数a的二进制形式的取位操作,即去a二进制形式的第x位。这里有一个重要应用就是a&1可以用于判断数a的奇偶性,即a末位为0即为偶数,末位为1即为奇数。

(2)异或运算(^):

具体介绍参考之前的随笔:http://www.cnblogs.com/COLIN-LIGHTNING/p/8298554.html

应用为交换两数:a^=b,b^=a,a^=b即完成了两数交换。

(3)按位左移(<<):

a<<=x即为使a乘以2的x次幂,原理是让a的二进制形式左移x位;应用为对与2的幂次方相乘使运算更快更方便;

(4)按位右移(>>):

a>>=x即为使a除以2的x次幂,原理是让a的二进制形式右移x位;应用为对与2的幂次方相除使运算更快更方便;

5.一般代码:

(1)递归形式:

int stein(int a,int b){
    if(a<b) a^=b,b^=a,a^=b;        //交换,使a为较大数;
    if(b==0)return a;                    //当相减为零,即两数相等时,gcd=a;
    if((!(a&1))&&(!(b&1))) return stein(a>>1,b>>1)<<1;   //s1,注意最后的左移,在递归返回过程中将2因子乘上;
    else if((a&1)&&(!(b&1)))return stein(a,b>>1);            //s2;
    else if((!(a&1))&&(b&1))return stein(a>>1,b);
    else return stein(a-b,b);                                             //s3;
} 

(2)迭代形式:

int stein(int a,int b){
    int k=1;
    while((!(a&1))&&(!(b&1))){    //s1;
        k<<=1;                          //用k记录全部公因子2的乘积 ;
        a>>=1;
        b>>=1;
    }
    while(!(a&1))a>>=1;              //s2;
    while(!(b&1))b>>=1;
    if(a<b) a^=b,b^=a,a^=b;        //交换,使a为较大数;
    while(a!=b){                           //s3;
        a-=b;
        if(a<b) a^=b,b^=a,a^=b;
    }
    return k*a;
}

原文地址:https://www.cnblogs.com/COLIN-LIGHTNING/p/8425484.html

时间: 2024-08-29 09:57:51

浅谈Stein算法求最大公约数(GCD)的原理及简单应用的相关文章

用python实现欧几里德算法求最大公约数

方法1: def gcd(x, y):   while n:       x, y = y, x % y   return x 方法2: def yue(x,y):      if y:              return gcd(y,x%y)      else:            return x 用python实现欧几里德算法求最大公约数,布布扣,bubuko.com

hdu1875浅谈prim算法的朴素实现

阅读原题 题目大意 给你几个(<=100)小岛的坐标,然后你把所有的岛都修上桥连接起来,求最小花费,还有个附加的限制:只有岛之间的距离大于等于10,或小于等于1000时才能修桥. 大概是因为十米以内不用建桥,千米以上无法建桥.哈哈,说着玩的. 很明显这是一道MST(最小生成树)的题目,貌似也有人用并查集AC过. 最小生成树算法 概述 最小生成树的常用算法有两个kruskal和prim算法.两者都是不停地执行归并操作,然而一言以蔽之,两者的不同之处在于:kruskal----归并边:prim---

【算法】欧几里德算法--求最大公约数

预备知识 因子(除数) 如果有整数 n,a,b .a和b都不为0 ,且 有 n = a*b ,则说a(或者b,以下省略说明)为n的一个因子,或者说a能整除n. 特别的:任何非0整数都是0的因子,所以一般我们不会去求0的因子. 如:3 的因子有  1, -1 ,  3 ,  -3 .然而我们一般只考虑正数因子,因为负数因子和正数因此没有本质上的区别,只是符号不同而已. 素数:素数(也加叫质数)的定义是,如果整数p的因子 只有 ±1 和   ±p,则它就是素数 .特别的:0 和1既不是素数,也不是合

浅谈分词算法(2)基于词典的分词方法

[TOC] 前言 在浅谈分词算法(1)分词中的基本问题中我们探讨了分词中的基本问题,也提到了基于词典的分词方法.基于词典的分词方法是一种比较传统的方式,这类分词方法有很多,如:正向最大匹配(forward maximum matching method, FMM).逆向最大匹配(backward maximum matching method,BMM).双向扫描法.逐词遍历法.N-最短路径方法以及基于词的n-gram语法模型的分词方法等等.对于这类方法,词典的整理选择在其中占到了很重要的作用,本

浅谈欧洲算法——模拟退火

初听说退火这个名词感觉就很(zhuang)帅(A__CDEFG...) 直到学了退火之后,我才发现: 退火不只是帅,而且非常万能 甚至比 D (大) F (法) S (师)还要万能 简直就是骗(de)分神器啊 简介 作为一个计算机算法,它竟然在百度上有物理词条! 当时我看了就懵了,你说计算机一个算法,跟冶炼金属有什么关系啊? 后来我看了算法的词条... 是不是更懵了... 方便大家理解(变得更懵),我搬了百度上的定义: Simulate Anneal Arithmetic (SAA,模拟退火算法

浅谈分词算法(1)分词中的基本问题

[TOC] 前言 分词或说切词是自然语言处理中一个经典且基础的问题,在平时的工作中也反复的接触到分词问题,用到了不同的模型,不同的方法应用在各个领域中,所以想对分词问题做一个系统的梳理.大多数分词问题主要是针对类似汉语.韩语.日语等,词语之间并没有天然的分割,而像英语等,句子中是带有天然的分割的.但是英语也会涉及到分词问题,比如实体识别.词性标注等内容.而本系列文章更多的是讨论汉语中的分词问题,首先我们从分词问题的基本出发,之后从传统的词典分词到将分词转为序列标注问题的分词,以及最新的结合深度学

[算法]求满足要求的进制(辗转相除(欧几里得算法),求最大公约数gcd)

题目 3在十进制下满足若各位和能被3整除,则该数能被3整除. 5在十六进制下也满足此规律. 给定数字k,求多少进制(1e18进制范围内)下能满足此规律,找出一个即可,无则输出-1. 题解 写写画画能找到规律,即是求与k互质的数x,x进制下即能满足上述规律. 相关 求最大公约数:辗转相除法(又叫欧几里得算法) 欧几里德定理:gcd(a, b) = gcd(b , a mod b) ,对于正整数a.b. 其中a.b大小无所谓.当a值小于b值时,算法的下一次递归调用就能够将a和b的值交换过来. 代码

使用stein 算法计算 最大公约数和最小公倍数

比欧几里得算法高效的用来计算gcd和lcm的stein算法,用来大数的计算: function gcd(a,b){ if(a == b){return a;} var bigger; var smaller; if(a>b){bigger = a;smaller = b;} else{bigger = b;smaller = a;} if(smaller == 0){return bigger;} if(bigger %2 == 0 && smaller % 2 == 0){ ret

欧几里德算法求最大公约数

求最大公约数有暴力法和辗转相除法 时间复杂度 暴力:O(N) 辗转相除法:O(2logN) 辗转相除法原理: 设c为A B 的最大公约数 则存在K1 K2 使 A=K1*c B=K2*c; r为A模B r=A - K3*B; r=K1*c-K3*k2*c; r=(K1-K2*K3)*c; 所以A 和 B 的余数一定是最大公约数c的倍数 1 #include <stdio.h> 2 3 int gcd(int a, int b) 4 { 5 int temp, r; 6 if(a<b) 7