Stein算法求最大公约数
首先引进一个符号: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算法求最大公约数的更多相关文章
- 浅谈Stein算法求最大公约数(GCD)的原理及简单应用
一.Stein算法过程及其简单证明 1.一般步骤: s1:当两数均为偶数时将其同时除以2至至少一数为奇数为止,记录除掉的所有公因数2的乘积k: s2:如果仍有一数为偶数,连续除以2直至该数为奇数为止: ...
- 使用Euclid算法求最大公约数
参考文章 1.<linux c编程一站式学习>的习题5.3.1 2.百度百科Euclid算法:https://baike.baidu.com/item/Euclid%E7%AE%97%E6 ...
- 最小公约数(欧几里得算法&&stein算法)
求最小公约数,最easy想到的是欧几里得算法,这个算法也是比較easy理解的,效率也是非常不错的. 也叫做辗转相除法. 对随意两个数a.b(a>b).d=gcd(a.b),假设b不为零.那么gc ...
- 求最大公约数(GCD)的两种算法
之前一直只知道欧几里得辗转相除法,今天学习了一下另外一种.在处理大数时更优秀的算法--Stein 特此记载 1.欧几里得(Euclid)算法 又称辗转相除法,依据定理gcd(a,b)=gcd(b,a% ...
- Python 最大公约数的欧几里得算法及Stein算法
greatest common divisor(最大公约数) 1.欧几里得算法 欧几里德算法又称辗转相除法,用于计算两个正整数a,b的最大公约数. 其计算原理依赖于下面的定理: 两个整数的最大公约数等 ...
- 【算法基础】欧几里得gcd求最大公约数
package Basic; import java.util.Scanner; public class Gcd { public static void main(String[] args) { ...
- 算法:辗转相除法求最大公约数(C语言实现)
辗转相除法,一种求最大公约数的算法 已知:A / B = C ······ R (A.B.C.R皆是整数) 假设:D是A的余数,D也是B的余数,那么D就是A和B的公约数 D是A和B的约数,则A和B是 ...
- [算法]求满足要求的进制(辗转相除(欧几里得算法),求最大公约数gcd)
题目 3在十进制下满足若各位和能被3整除,则该数能被3整除. 5在十六进制下也满足此规律. 给定数字k,求多少进制(1e18进制范围内)下能满足此规律,找出一个即可,无则输出-1. 题解 写写画画能找 ...
- 算法:欧几里得求最大公约数(python版)
#欧几里得求最大公约数 #!/usr/bin/env python #coding -*- utf:8 -*- #iteration def gcd(a,b): if b==0: return a e ...
随机推荐
- Oracle_PL/SQL(5) 包
包1.定义:包用于逻辑组合相关的PL/SQL类型,项和子程序,由包规范和包体组成 建立包规范:包规范是包与应用程序之间的接口,用于定义包的公用组件, 包括常量,变量,游标,过程,函数等 建立包体:用于 ...
- hdu 1010(DFS) 骨头的诱惑
http://acm.hdu.edu.cn/showproblem.php?pid=1010 题目大意从S出发,问能否在时间t的时候到达终点D,X为障碍 需要注意的是要恰好在t时刻到达,而不是在t时间 ...
- Pandas设置值
1.创建数据 >>> dates = pd.date_range(', periods=6) >>> df = pd.DataFrame(np.arange(24) ...
- 三分钟分布式CAP理论
分布式系统架构理论,定义了三种指标,理论说我们最多只能满足两个. ## 分布式系统 首先我们这个理论所说的分布式系统,是指系统内会共享数据,互相有连接有交互,才能完成系统功能的的分布式系统.而这个理论 ...
- SQL Server 2008重新保存表时出错
在使用SQL Server 2008时,修改了表的字段名和类型名之后,点击保存按钮之后出现如下对话框:
- ZOJ2412 Farm Irrigation(农田灌溉) 搜索
Farm Irrigation Time Limit: 2 Seconds Memory Limit: 65536 KB Benny has a spacious farm land to ...
- C#程序如何以管理员身份运行
VISTA 和 Windows 7 都使用了UAC来控制程序访问,对于一些需要使用管理员身份运行的程序就得右键以管理员身份运行. C# 编程中可以使程序自动使用管理员身份运行,也就是我们常常看到一些程 ...
- Xcode 折叠代码快捷键
Xcode9之前版本可以代码局部和全局折叠,但是9之后只能以某个函数为单位进行全局折叠,特别是里面的逻辑判断的代码不能局部折叠了... Xcode9之前版本代码折叠: 在Xcode菜单里选择Prefe ...
- Convert 实现 pdf 和图片格式互转
pdf 转换为图片 (注意:pdf 默认转换的是透明背景,如果转为jpg格式必须添加背景色.-background white -flatten) convert -background white ...
- 常用的 composer 命令
一.列表内容 composer composer list二.查看当前镜像源 composer config -l -g [repositories.packagist.org.type] compo ...