二进制GCD

    GCD这种通用的算法相信每个OLER都会 ,辗转相除,代码只有四行 :

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

  GCD算法使通过辗转相除法来求解两个数的最大公因数,又称欧几里得算法

     可以知道:GCD(x,y)=GCD(x,y-x)

     我们将b能被a整除记作a|b

     那么假设z是最大公因数,那么有:

            如果z|x,z|y,则z|(y-x)  (因为x和y肯定可以写作a*z=x,b*z=y,那么a*z-b*z=(a-b)*z,一定可以整除)

     那么再设z不是x的因子,则z不是x和y-x的公因子

     设z|x.z不是y的因子,则z不是x和y-x的公因子

     那么代码就是上面那个啦!

如果想进一步提高这个算法的效率,那么我们可以选择二进制GCD

    我们可以通过不断地筛去因子2来提高算法的效率,这样的2可以是公共的或单个的,总之不影响算法的正确性

    那么为什么不是筛去因子3、因子4呢?

    因为计算机只提供2进制的快速运算(按位),所以判断a%2=?0可以直接写成!(a&1),但是其它数是没有的,我们知道计算机做取模运算的效率是很低很低的。

    那下面我们来看一看证明过程:

    GCD(x,y)=x   (x==y)

    GCD(x,y)=2*(GCD(x/2,y/2))  (!(x&1) and !(y&1))

    GCD(x,y)=GCD(x/2,y) (!(x&1) and (y&1)    因为2显然不是公因数,所以我们可以果断地筛掉它)

    GCD(x,y)=GCD(x,y/2) ((x&1) and !(y&1)    理由同上)

    GCD(x,y)=GCD(x-y,y) (辗转相减) 

    那么通过上面的推理,我们可以得出代码:

int GCD(int x,int y){
int i=0,j=0;
if(x==0) return y;//if和for一定不能反,要么会炸
if(y==0) return x;//一个没用了就返回另一个
for(i;0==(x&1);i++) x>>=1;//化简为n*(m^2)形式
for(j;0==(y&1);j++) y>>=1;//化简为a*(b^2)形式
if(i>j) i=j;//去最大 公 因数,当然是你有我有的了
while(1){
if(x<y) x^=y,y^=x,x^=y;//二进制交换,非常高级
if(0==(x-=y)) return y<<i;//那么就把以前的次幂乘上去,辗转减操作
while(0==(x&1)) x>>=1;//x减了y以后可能还是成为a*(b^2)形式,要继续筛去
}
}

  

至于LCM(最小公倍数)来说有如下定理:

    x*y=LCM(x,y)*GCD(x,y),那么只需要求出GCD以后算一下x*y/GCD(x,y)就好了

【数论】二进制GCD的更多相关文章

  1. 二进制GCD算法解析

    UPD 2018.3.30 这个好像就是更相减损术的样子emmm UPD 2018.5.22 好像不是更相减损术而是叫Stein算法的样子emmm 蒟蒻来做个二进制GCD笔记. 为什么要写这个东西呢, ...

  2. 二进制GCD

    目录 写在前面 具体实现: Code 写在前面 全程抄书 想要进一步提高求 \(\gcd\) 的效率,可以通过不断去除因子 \(2\) 来降低常数,这就是"二进制 \(\gcd\) &quo ...

  3. 二进制GCD算法 减少%的时间消耗

    /* 二进制求最大公约数.由于传统的GCD,使用了%,在计算机运行过程中要花费大量的时间,所以,采取二进制的求法,来减少时间的消耗. 算法: 当a,b都是偶数时: gcd(a,b)=2*gcd(a/2 ...

  4. CodeForces - 984C——Finite or not?分数整除问题(数论,gcd)

    题目传送门 题目描述:给你一个p/q,让你求在b进制下,这个小数是不是有限小数. 思路: 先来膜拜一个大神的博客,如何求小数的二进制表达,(感谢博主肘子zhouzi).然后小数的其他进制表达也一样. ...

  5. HDU - 5050 (大数二进制gcd)

    It's time to fight the local despots and redistribute the land. There is a rectangular piece of land ...

  6. 数论3——gcd&&lcm

    gcd(a, b),就是求a和b的最大公约数 lcm(a, b),就是求a和b的最小公倍数 然后有个公式 a*b = gcd * lcm     ( gcd就是gcd(a, b), ( •̀∀•́ ) ...

  7. codeforce#483div2C-Finite or not?数论,GCD

    传送门:http://codeforces.com/contest/984/problem/C 这道题 题意:求q/p是否能用k进制有限表示小数点后的数:   思路:数学推理:     1.首先把q/ ...

  8. C. Neko does Maths(数论 二进制枚举因数)

     题目链接:https://codeforces.com/contest/1152/problem/C 题目大意:给你a和b,然后让你找到一个k,使得a+k和b+k的lcm. 学习网址:https:/ ...

  9. 用二进制方法求两个整数的最大公约数(GCD)

    二进制GCD算法基本原理是: 先用移位的方式对两个数除2,直到两个数不同时为偶数.然后将剩下的偶数(如果有的话)做同样的操作,这样做的原因是如果u和v中u为偶数,v为奇数,则有gcd(u,v)=gcd ...

随机推荐

  1. ECMAScript中关于如何获取this的定义

    文章中一些名词的翻译存疑,没有查过正式的中文名称 前面都是具体过程的解释,懒得看可以直接看获取思路 有关this的取值请移步JavaScript笔记--this的取值 获取this的过程 Runtim ...

  2. mysql相似于oracle的to_char() to_date()方法

    mysql日期和字符相互转换方法, date_format(date,'%Y-%m-%d')  -------------->oracle中的to_char(); str_to_date(dat ...

  3. [LintCode] Longest Increasing Continuous Subsequence 最长连续递增子序列

    Give an integer array,find the longest increasing continuous subsequence in this array. An increasin ...

  4. servlet session 相关

    1.session是server维护的一个变量,如果消除每个session?----这里只做指定key的session删除 1.1.显示调用 废除指定key的session session.remov ...

  5. $.ajax用法与举例

    下面是一段比较常用到的 $.ajax 方法: $.ajax({ type:'GET', url:'http://www.phpernote.com/jquery.php', data:{usernam ...

  6. bzoj1222: [HNOI2001]产品加工--DP

    DP神题orz dp[i]表示机器1工作i小时,机器2工作dp[i]小时 那么对于每个任务: 选1:dp[i]=dp[i-a]; 选2:dp[i]=dp[i]+b; 选1+2:dp[i]=dp[i-c ...

  7. jquery_插件

    编写插件的目的:给已有的一些列方法或函数做一个封装 jquery插件推荐命名方式 :jquery.[插件名].js  防止与插件库混淆 所有对象方法都应当附加到jquery.fn 对象上,所有的全局函 ...

  8. github 离线版本下载

    http://download.csdn.net/download/nevinblog/9031049

  9. Unity3d优化

    检测方式: 一,Unity3D 渲染统计窗口 Game视窗的Stats去查看渲染统计的信息: 1.FPS fps其实就是 frames per second,也就是每一秒游戏执行的帧数,这个数值越小, ...

  10. Ubuntu下编译第一个C程序的成功运行

    1. 打开控制台:使用快捷键 Ctrl + Alt + T: 2.  安装gcc为C语言编译器,g++为C++ 语言编译器 sudo apt-get install g++. 3.  编辑好hello ...