首先引进一个符号:gcd是greatest common divisor(最大公约数)的缩写,gcd( x,y ) 表示x和y的最大公约数。然后有一个事实需要了解:一个奇数的所有约数都是奇数。这个很容易,下面我们要用到。 

    来研究一下最大公约数的性质,我们发现有 gcd( k*x,k*y ) = k*gcd( x,y ) 这么一个非常好的性质(证明我就省去了)。说他好是因为他非常符合我们化小的思想。我们试取 k=2 ,则有 gcd( 2x,2y ) = 2 * gcd( x,y )。这使我们很快联想到将两个偶数化小的方法。那么一奇一个偶以及两个奇数的情况我们如何化小呢?

先来看看一奇一偶的情况: 设有2x和y两个数,其中y为奇数。因为y的所有约数都是奇数,所以 a = gcd( 2x,y ) 是奇数。根据2x是个偶数不难联想到,a应该是x的约数。我们来证明一下:(2x)%a=0,设2x=n*a,因为a是奇数,2x是偶数,则必有n是偶数。又因为 x=(n/2)*a,所以 x%a=0,即a是x的约数。因为a也是y的约数,所以a是x和y的公约数,有 gcd( 2x,y ) <= gcd( x,y )。因为gcd( x,y )明显是2x和y的公约数,又有gcd( x,y ) <= gcd( 2x,y ),所以 gcd( 2x,y ) = gcd( x,y )。至此,我们得出了一奇一偶时化小的方法。

再来看看两个奇数的情况:设有两个奇数x和y,似乎x和y直接向小转化没有什么太好的办法,我们可以绕个道,把x和y向偶数靠拢去化小。不妨设x>y,我们注意到x+y和x-y是两个偶数,则有 gcd( x+y,x-y ) = 2 * gcd( (x+y)/2,(x-y)/2 ),那么 gcd( x,y ) 与 gcd( x+y,x-y ) 以及 gcd( (x+y)/2,(x-y)/2 ) 之间是不是有某种联系呢?为了方便我设 m=(x+y)/2 ,n=(x-y)/2 ,容易发现 m+n=x ,m-n=y 。设 a = gcd( m,n ),则 m%a=0,n%a=0 ,所以 (m+n)%a=0,(m-n)%a=0 ,即 x%a=0 ,y%a=0 ,所以a是x和y的公约数,有 gcd( m,n )<= gcd(x,y)。再设 b = gcd( x,y )肯定为奇数,则 x%b=0,y%b=0 ,所以 (x+y)%b=0 ,(x-y)%b=0 ,又因为x+y和x-y都是偶数,跟前面一奇一偶时证明a是x的约数的方法相同,有 ((x+y)/2)%b=0,((x-y)/2)%b=0 ,即 m%b=0 ,n%b=0 ,所以b是m和n的公约数,有 gcd( x,y ) <= gcd( m,n )。所以 gcd( x,y ) = gcd( m,n ) = gcd( (x+y)/2,(x-y)/2 )。

我们来整理一下,对两个正整数 x>y :
1.均为偶数 gcd( x,y ) =2gcd( x/2,y/2 );

2.均为奇数 gcd( x,y ) = gcd( (x+y)/2,(x-y)/2 );

2.x奇y偶   gcd( x,y ) = gcd( x,y/2 );

3.x偶y奇   gcd( x,y ) = gcd( x/2,y )  或 gcd( x,y )=gcd( y,x/2 );

现在我们已经有了递归式,还需要再找出一个退化情况。注意到 gcd( x,x ) = x ,我们就用这个。

#include <cstdio>
#include <cstdlib>
#include <iostream>
using namespace std; int Stein(int x,int y)
{
int ans = 0,tmp;
if(x<y){
swap(x,y);
}
if(y==0) return x;//0能被任何非0数整除
while(x!=y)
{
if(x&1){//x&0x1(0x表示16#)
if(y&1){//x,y同为奇数时
y = (x-y)>>1;
x -= y;
}else{//x为奇数,y为偶数时
y>>=1;
}
}else{
if(y&1){//x为偶数,y为奇数
x>>=1;
if(x<y) swap(x,y);
}else{//x,y都为偶数
x>>=1;
y>>=1;
ans++;
}
}
}
return x<<ans;
}
int main()
{
//freopen("input.txt","r",stdin);
int x,y; while(~scanf("%d%d",&x,&y))
{
int ans = Stein(x,y);
printf("%d\n",ans);
}
return 0;
}

Stein算法求最大公约数的更多相关文章

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

    一.Stein算法过程及其简单证明 1.一般步骤: s1:当两数均为偶数时将其同时除以2至至少一数为奇数为止,记录除掉的所有公因数2的乘积k: s2:如果仍有一数为偶数,连续除以2直至该数为奇数为止: ...

  2. 使用Euclid算法求最大公约数

    参考文章 1.<linux c编程一站式学习>的习题5.3.1 2.百度百科Euclid算法:https://baike.baidu.com/item/Euclid%E7%AE%97%E6 ...

  3. 最小公约数(欧几里得算法&amp;&amp;stein算法)

    求最小公约数,最easy想到的是欧几里得算法,这个算法也是比較easy理解的,效率也是非常不错的. 也叫做辗转相除法. 对随意两个数a.b(a>b).d=gcd(a.b),假设b不为零.那么gc ...

  4. 求最大公约数(GCD)的两种算法

    之前一直只知道欧几里得辗转相除法,今天学习了一下另外一种.在处理大数时更优秀的算法--Stein 特此记载 1.欧几里得(Euclid)算法 又称辗转相除法,依据定理gcd(a,b)=gcd(b,a% ...

  5. Python 最大公约数的欧几里得算法及Stein算法

    greatest common divisor(最大公约数) 1.欧几里得算法 欧几里德算法又称辗转相除法,用于计算两个正整数a,b的最大公约数. 其计算原理依赖于下面的定理: 两个整数的最大公约数等 ...

  6. 【算法基础】欧几里得gcd求最大公约数

    package Basic; import java.util.Scanner; public class Gcd { public static void main(String[] args) { ...

  7. 算法:辗转相除法求最大公约数(C语言实现)

    辗转相除法,一种求最大公约数的算法 已知:A / B = C ······ R  (A.B.C.R皆是整数) 假设:D是A的余数,D也是B的余数,那么D就是A和B的公约数 D是A和B的约数,则A和B是 ...

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

    题目 3在十进制下满足若各位和能被3整除,则该数能被3整除. 5在十六进制下也满足此规律. 给定数字k,求多少进制(1e18进制范围内)下能满足此规律,找出一个即可,无则输出-1. 题解 写写画画能找 ...

  9. 算法:欧几里得求最大公约数(python版)

    #欧几里得求最大公约数 #!/usr/bin/env python #coding -*- utf:8 -*- #iteration def gcd(a,b): if b==0: return a e ...

随机推荐

  1. jQuery的节点选择

    jQuery.parent(expr) 找父亲节点,可以传入expr进行过滤,比如$("span").parent()或者$("span").parent(&q ...

  2. Mercedes offline programming/coding tips and guides

    Mercedes offline programming/coding recommendations and guides: Offline coding: SCN or CVN coding wa ...

  3. Eclipse安装和使用windowbuilder插件开发图形界面

    windowbuilder插件的安装 windowbuilder的官方网站:http://www.eclipse.org/windowbuilder/download.php 在Eclipse中 安装 ...

  4. Python之路(第三篇):Python基本数据类型字符串(二)

    一.基本数据类型1.字符串 str字符串方法介绍(二)a --expandtabs( ) expandtabs( ) 把字符串中的 tab 符号('\t')转为空格参数默认为8,注意字符串原有的空格也 ...

  5. 摹客首家发布Adobe XD插件

    10月19日,摹客iDoc发布了支持Adobe XD的插件,这是中国国内首款基于Adobe XD 正式API的插件. 设计师在Adobe XD 中安装并使用此插件,可以将设计稿上传到摹客iDoc,并使 ...

  6. Roslyn研究随笔

    Roslyn概述: http://blogs.ejb.cc/archives/7604/dotnet-compile-platform-roslyn-overview 使用Microsoft Rosl ...

  7. python之Bottle框架

    一.简单的Bottle框架 1)bottle框架简介 安装 pip install bottle Bottle是一个快速.简洁.轻量级的基于WSIG的微型Web框架. 此框架只由一个 .py 文件,除 ...

  8. 33、iOS10 由于权限问题导致崩溃的大坑

    控制台报忠告: This app has crashed because it attempted to access privacy-sensitive data without a usage d ...

  9. yum安装nginx 加载image_filter 加载方式

    通过yum安装的nginx 加载image_filter方式方法: yum install -y gd-devel libgd gcc libgdyum install -y nginx-module ...

  10. Oracle导入的常见语句

    登录sql > sqlplus / as sysdba 创建表空间sql > create tablespace TABLESPACE datafile 'e:\tables1.dbf' ...