GCD,快速GCD,扩展GCD
/*==================================================*\
| GCD 最大公约数
\*==================================================*/
int gcd(int x, int y)
{ if (!x || !y) return x > y ? x : y; for (int t; t = x % y; x = y, y = t); return y;
}
/*==================================================*\
| 快速 GCD
\*==================================================*/
int kgcd(int a, int b)
{ if (a == 0) return b; if (b == 0) return a; if (!(a & 1) && !(b & 1)) return kgcd(a>>1, b>>1)<<1;else if (!(b & 1))return kgcd(a, b>>1); else if (!(a & 1)) return kgcd(a>>1, b); else return kgcd(abs(a - b), min(a, b));
}
/*==================================================*\
| 扩展 GCD
| 求x, y使得gcd(a, b) = a * x + b * y;
\*==================================================*/
int extgcd(int a, int b, int & x, int & y)
{ if (b == 0) { x=1; y=0; return a; } int d = extgcd(b, a % b, x, y); int t = x; x = y; y = t - a / b * y; return d;
}
欧几里得算法
欧几里德算法又称辗转相除法,用于计算两个整数a,b的最大公约数。其计算原理依赖于下面的定理:
定理:gcd(a,b) = gcd(b,a mod b)
证明:a可以表示成a = kb + r,则r = a mod b
假设d是a,b的一个公约数,则有
d|a, d|b,而r = a – kb,因此d|r
因此d是(b,a mod b)的公约数
假设d 是(b,a mod b)的公约数,则
d | b , d |r ,但是a = kb +r
因此d也是(a,b)的公约数
因此(a,b)和(b,a mod b)的公约数是一样的,其最大公约数也必然相等,得证.
扩展欧几里德算法
扩展欧几里德算法是用来在已知a, b求解一组p,q使得p * a+q * b = Gcd(a, b) (解一定存在,根据数论中的相关定理)。扩展欧几里德常用在求解模线性方程及方程组中。下面是一个使用C++的实现:
int exGcd(int a, int b, int &x, int &y)
{if(b == 0){x = 1;y = 0;return a;}int r = exGcd(b, a % b, x, y);int t = x;x = y;y = t – a / b * y;return r;
}
把这个实现和Gcd的递归实现相比,发现多了下面的x,y赋值过程,这就是扩展欧几里德算法的精髓。
可以这样思考:
对于a’ = b, b’ = a % b 而言,我们求得 x, y使得 a’x + b’y = Gcd(a’, b’)
由于b’ = a % b = a – a / b * b (注:这里的/是程序设计语言中的除法)
那么可以得到:
a’x + b’y = Gcd(a’, b’) ==>
bx + (a – a / b * b)y = Gcd(a’, b’) = Gcd(a, b) ==>
ay +b(x – a / b*y) = Gcd(a, b)
因此对于a和b而言,他们的相对应的p,q分别是 y和(x-a/b*y)
补充:关于使用扩展欧几里德算法解决不定方程的办法
对于不定整数方程pa+qb=c,若 c mod Gcd(p, q)=0,则该方程存在整数解,否则不存在整数解。
上面已经列出找一个整数解的方法,在找到p * a+q * b = Gcd(p, q)的一组解p0,q0后,p * a+q * b = Gcd(p, q)的其他整数解满足:
p = p0 + b/Gcd(p, q) * t
q = q0 – a/Gcd(p, q) * t(其中t为任意整数)
至于pa+qb=c的整数解,只需将p * a+q * b = Gcd(p, q)的每个解乘上 c/Gcd(p, q) 即可
#include <iostream>
using namespace std;
//int gcd(int a, int b); //两个数的最大公约数
//int ngcd(int *pa, int n) //N个数的最大公约数
//int lcm(int a, int b) //两个数的最小公倍数
//int nlcm(int *pa, int n) //N个数的最小公倍数 int gcd (int a,int b)
{ if (b==0) return a; return gcd(b,a%b);
} int ngcd(int *pa, int n)
{ if(n == 1) return *pa; return (gcd(pa[n-1], ngcd(pa, n-1)));
} int lcm(int a, int b) //最小公倍数 = 两数乘积 / 最大公约数
{ return a*b/gcd(a, b);
} int nlcm(int *pa, int n)
{ if(n == 1) return *pa; return lcm(pa[n-1], nlcm(pa, n-1));
} int main()
{ int a,b,n,rgcd,rlcm,rngcd,rnlcm; int pa[10]; printf("please input tow number:"); scanf("%d %d",&a,&b); rgcd=gcd(a,b); rlcm=lcm(a,b); printf("最大公约数是:%d\n",rgcd); printf("最小公倍数是:%d\n",rlcm); printf("please input the n:"); scanf("%d",&n); for (int i=0;i<n;i++) scanf("%d",&pa[i]); rngcd=ngcd(pa,n); rnlcm=nlcm(pa,n); printf("最大公约数是:%d\n",rngcd); printf("最小公倍数是:%d\n",rnlcm); return 0;
}
GCD,快速GCD,扩展GCD相关推荐
- POJ-2065 SETI 高斯消元,扩展GCD
该题题义是给定如下一个方程组: F(1) = C1 (mod) P F(2) = C2 (mod) P F(3) = C3 (mod) P ... 其中F(1) = A(1,1)*x1 + A(1, ...
- 模板—扩展GCD*2
有必要重新学一下扩展GCD emmmm. 主要是扩展GCD求解线性同余方程$ax≡b (mod p)$. 1.方程有解的充分必要条件:b%gcd(a,p)=0. 证明: $ax-py=b$ 由于求解整 ...
- 扩展gcd codevs 1200 同余方程
codevs 1200 同余方程 2012年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 求关 ...
- UESTC 288 青蛙的约会 扩展GCD
设两只青蛙跳了t步,则此时A的坐标:x+mt,B的坐标:y+nt.要使的他们在同一点,则要满足: x+mt - (y+nt) = kL (p是整数) 化成: (n-m)t + kL = x-y (L ...
- GCD及其扩展GCD详解
转自:http://www.cnblogs.com/yuelingzhi/archive/2011/08/13/2137582.html 扩展欧几里德算法-求解不定方程,线性同余方程. 设过s步后两青 ...
- POJ 1061 青蛙的约会(扩展GCD求模线性方程)
题目地址:POJ 1061 扩展GCD好难懂..看了半天,终于把证明什么的都看明白了..推荐一篇博客吧(戳这里),讲的真心不错.. 直接上代码: #include <iostream> # ...
- 用GCD线程组与GCD信号量将异步线程转换为同步线程
用GCD线程组与GCD信号量将异步线程转换为同步线程 有时候我们会碰到这样子的一种情形: 同时获取两个网络请求的数据,但是网络请求是异步的,我们需要获取到两个网络请求的数据之后才能够进行下一步的操作, ...
- HDU 5869.Different GCD Subarray Query-区间gcd+树状数组 (神奇的标记右移操作) (2016年ICPC大连网络赛)...
树状数组... Different GCD Subarray Query Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/6 ...
- FVD speed dial-firefox下漂亮和功能强大的快速拨号扩展
你是否一直使用快速拨号来浏览你最喜爱的网站?那么你就需要一个带有FVD speed dial扩展的firefox浏览器.虽然在火狐之中有很多同类扩展,但是FVD快速拨号应该是其中的上上之作,集人性化. ...
最新文章
- Adam 那么棒,为什么还对 SGD 念念不忘?一个框架看懂深度学习优化算法
- from torch._C import * ImportError: DLL load failed 动态链接库(DLL)初始化例程失败
- 如何在 Kubernetes Pod 内进行网络抓包
- 2015/8/18 Python基本使用(2)
- oracle多表嵌套查询使用,oracle sql 多表 嵌套子查询 连接查询, join where exist i...
- SSRS 2012 高级图表类型 -- 气泡图与散点图
- 基于Python的数据分析
- 11-24 EDEM-FLUENT 耦合步骤
- boot camp驱动下载以及对应机型版本查询
- hibernate的注解属性mappedBy详解
- python调用java之jpype参数类型转换
- windows无法访问 计算机打印机,windows 7 无法连接到打印机 (错误0x0000000d)的解决方法...
- double类型判断是否相等
- 样式和多级编号的关系
- (Tiled官方文档翻译)第四节:对象的编辑和使用
- windows 快捷键之新建文件夹
- import win32api, sys, os ImportError: DLL load failed: The specified module could not be found.
- 【5 操作系统调度】
- 生活中正确购买物品你可能真的不会!
- 算法面试手撕代码高频题汇集
热门文章
- 算法题:用php生成excel列
- 基于LBS任务式旅游APP
- 模电之半导体基础篇1(本征半导体、杂质半导体)
- Imagemotion for Mac(PS动画插件)
- Hive启动报错:java.net.URISyntaxException: Relative path in absolute URI: ${system:user.name%7D
- python教程68--cufflinks库绘图功能
- SAP JCo 3.0 下载
- VMware Workstation 12序列号: 5A02H-AU243-TZJ49-GTC7K-3C61N
- 银行信贷管理系统的客户关系管理子模块
- @Caching,@Cacheable,@CachePut的使用