【数论】二进制GCD
二进制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的更多相关文章
- 二进制GCD算法解析
UPD 2018.3.30 这个好像就是更相减损术的样子emmm UPD 2018.5.22 好像不是更相减损术而是叫Stein算法的样子emmm 蒟蒻来做个二进制GCD笔记. 为什么要写这个东西呢, ...
- 二进制GCD
目录 写在前面 具体实现: Code 写在前面 全程抄书 想要进一步提高求 \(\gcd\) 的效率,可以通过不断去除因子 \(2\) 来降低常数,这就是"二进制 \(\gcd\) &quo ...
- 二进制GCD算法 减少%的时间消耗
/* 二进制求最大公约数.由于传统的GCD,使用了%,在计算机运行过程中要花费大量的时间,所以,采取二进制的求法,来减少时间的消耗. 算法: 当a,b都是偶数时: gcd(a,b)=2*gcd(a/2 ...
- CodeForces - 984C——Finite or not?分数整除问题(数论,gcd)
题目传送门 题目描述:给你一个p/q,让你求在b进制下,这个小数是不是有限小数. 思路: 先来膜拜一个大神的博客,如何求小数的二进制表达,(感谢博主肘子zhouzi).然后小数的其他进制表达也一样. ...
- HDU - 5050 (大数二进制gcd)
It's time to fight the local despots and redistribute the land. There is a rectangular piece of land ...
- 数论3——gcd&&lcm
gcd(a, b),就是求a和b的最大公约数 lcm(a, b),就是求a和b的最小公倍数 然后有个公式 a*b = gcd * lcm ( gcd就是gcd(a, b), ( •̀∀•́ ) ...
- codeforce#483div2C-Finite or not?数论,GCD
传送门:http://codeforces.com/contest/984/problem/C 这道题 题意:求q/p是否能用k进制有限表示小数点后的数: 思路:数学推理: 1.首先把q/ ...
- C. Neko does Maths(数论 二进制枚举因数)
题目链接:https://codeforces.com/contest/1152/problem/C 题目大意:给你a和b,然后让你找到一个k,使得a+k和b+k的lcm. 学习网址:https:/ ...
- 用二进制方法求两个整数的最大公约数(GCD)
二进制GCD算法基本原理是: 先用移位的方式对两个数除2,直到两个数不同时为偶数.然后将剩下的偶数(如果有的话)做同样的操作,这样做的原因是如果u和v中u为偶数,v为奇数,则有gcd(u,v)=gcd ...
随机推荐
- jq图片点击居中放大原始图片兼容ie
/* *鍥剧墖澶у浘鏄剧ず */ function imgshow(){ content_div:"";//内容 bg_div:"";//背景变暗 img_di ...
- MySQL数据库相关命令
1.命令:show create table 表名 功能:获取建表语句 2.命令:desc 表名 功能:展示表字段及其类型
- window svn backup.bat
help command /? call /? %cd% 可以用在批处理文件中,也可以用在命令行中:展开后,是驱动器盘符:+当前目录,如在dos窗口中进入c:\dir目录下面, %0代指批处理文件自身 ...
- k-折交叉验证(k-fold crossValidation)
k-折交叉验证(k-fold crossValidation): 在机器学习中,将数据集A分为训练集(training set)B和测试集(test set)C,在样本量不充足的情况下,为了充分利用数 ...
- EmguCV 一些结构
一.MCvTermCriteria epsilon Epsilon max_iter Maximum iteration type CV_TERMCRIT value 二.MCvScalar vo T ...
- SQL优化 1
SQL_ID:fvdwtfv18yy0m 先看看sql的预估执行计划 select * from table(dbms_xplan.display_awr('fvdwtfv18yy0m')); sql ...
- Enum的使用
在项目开发中经常会使用到枚举,下面将举个例子,展示枚举的使用,不说废话,直接上代码. package com.tom.enumTest; public enum StatusType { A(&quo ...
- Git: untrack a file in local repo only and keep it in the remote repo
You could update your index: git update-index --assume-unchanged nbproject/project.properties and ma ...
- ArcGIS Server GP服务发布与测试(基础版)
版本:ArcGIS Server 10.4 环境:win10 测试目标:创建一个GP服务,功能为根据要素属性信息(如FID)选择出输入内容的对应匹配要素. 注:这个测试非常基础,仅供新手发布GP ...
- ngModel
https://docs.angularjs.org/error/ngModel/numfmt?p0=sa angular.module('myApp', []) .directive('tagLis ...