gcd和拓展gcd算法
gcd算法是用来求两个数最大公约数的算法,他是依靠辗转相除(中国好像叫辗转相减)法来求两个数的最大公约数,别的地方也有很多介绍不做过多赘述,主要提供代码供自己参考。
- gcd(int a,int b)
- {
- return b==?a:gcd(b,a%b);
- }
对于拓展gcd,是对方程ax+by=c求解;
就是a mod b=c这个方程求解;
具体看代码,不做过多赘述因为别人已经讲的很详细了,在这里copy一下别人的讲解:
我们其实只需要考虑形如 a • x mod n = 1 的方程。因为,如果能解出这样的方程, a • x mod n = 2 、 a • x mod n = 3 也都自动地获解了。假如 a • x mod n = 1 有一个解 x = 100 ,由于 100 个 a 除以 n 余 1 ,自然 200 个 a 除以 n 就余 2 , 300 个 a 除以 n 就余 3 ,等等,等式右边余数不为 1 的方程也都解开了。
让我们尝试求解 115x mod 367 = 1 。注意,由于 115 和 367 是互质的,因此方程确实有解。我们解方程的基本思路是,不断寻找 115 的某个倍数以及 367 的某个倍数,使得它们之间的差越来越小,直到最终变为 1 。由于 367 除以 115 得 3 ,余 22 ,因而 3 个 115 只比 367 少 22 。于是, 15 个 115 就要比 5 个 367 少 110 ,从而 16 个 115 就会比 5 个 367 多 5 。好了,真正巧妙的就在这里了: 16 个 115 比 5 个 367 多 5 ,但 3 个 115 比 1 个 367 少 22 ,两者结合起来,我们便能找到 115 的某个倍数和 367 的某个倍数,它们只相差 2 : 16 个 115 比 5 个 367 多 5 ,说明 64 个 115 比 20 个 367 多 20 ,又考虑到 3 个 115 比 1 个 367 少 22 ,于是 67 个 115 只比 21 个 367 少 2 。现在,结合“少 2 ”和“多 5 ”两个式子,我们就能把差距缩小到 1 了: 67 个 115 比 21 个 367 少 2 ,说明 134 个 115 比 42 个 367 少 4 ,而 16 个 115 比 5 个 367 多 5 ,于是 150 个 115 比 47 个 367 多 1 。这样,我们就解出了一个满足 115x mod 367 = 1 的 x ,即 x = 150 。大家会发现,在求解过程,我们相当于对 115 和 367 做了一遍辗转相除:我们不断给出 115 的某个倍数和 367 的某个倍数,通过辗转对比最近的两个结果,让它们的差距从“少 22 ”缩小到“多 5 ”,再到“少 2 ”、“多 1 ”,其中 22, 5, 2, 1 这几个数正是用辗转相除法求 115 和 367 的最大公约数时将会经历的数。因而,算法的步骤数仍然是对数级别的,即使面对上百位上千位的大数,计算机也毫无压力。这种求解方程 a • x mod n = b 的算法就叫做“扩展的辗转相除法”。
注意,整个算法有时也会以“少 1 ”的形式告终。例如,用此方法求解 128x mod 367 = 1 时,最后会得出 43 个 128 比 15 个 367 少 1 。这下怎么办呢?很简单, 43 个 128 比 15 个 367 少 1 ,但是 367 个 128 显然等于 128 个 367 ,对比两个式子可知, 324 个 128 就会比 113 个 367 多 1 了,于是得到 x = 324 。
最后还有一个问题:我们最终总能到达“多 1 ”或者“少 1 ”,这正是因为一开始的两个数是互质的。如果方程 a • x mod n = b 当中 a 和 n 不互质,它们的最大公约数是 d > 1 ,那么在 a 和 n 之间做辗转相除时,算到 d 就直接终止了。自然,扩展的辗转相除也将在到达“多 1 ”或者“少 1 ”之前提前结束。那怎么办呢?我们有一种巧妙的处理方法:以 d 为单位重新去度量 a 和 n (或者说让 a 和 n 都除以 d ),问题就变成我们熟悉的情况了。让我们来举个例子吧。假如我们要解方程 24 • x mod 42 = 30 ,为了方便后面的解释,我们来给这个方程编造一个背景:说一盒鸡蛋 24 个,那么买多少盒鸡蛋,才能让所有的鸡蛋 42 个 42 个地数最后正好能余 30 个?我们发现 24 和 42 不是互质的,扩展的辗转相除似乎就没有用了。不过没关系。我们找出 24 和 42 的最大公约数,发现它们的最大公约数是 6 。现在,让 24 和 42 都来除以 6 ,分别得到 4 和 7 。由于 6 已经是 24 和 42 的公约数中最大的了,因此把 24 和 42 当中的 6 除掉后,剩下的 4 和 7 就不再有大于 1 的公约数,从而就是互质的了。好了,现在我们把题目改编一下,把每 6 个鸡蛋视为一个新的单位量,比如说“ 1 把”。记住, 1 把鸡蛋就是 6 个鸡蛋。于是,原问题就变成了,每个盒子能装 4 把鸡蛋,那么买多少盒鸡蛋,才能让所有的鸡蛋 7 把 7 把地数,最后正好会余 5 把?于是,方程就变成了 4 • x mod 7 = 5 。由于此时 4 和 7 是互质的了,因而套用扩展的辗转相除法,此方程一定有解。可以解出特解 x = 3 ,在它的基础上加减 7 的整倍数,可以得到其他所有满足要求的 x 。这就是改编之后的问题的解。但是,虽说我们对原题做了“改编”,题目内容本身却完全没变,连数值都没变,只不过换了一种说法。改编后的题目里需要买 3 盒鸡蛋,改编前的题目里当然也是要买 3 盒鸡蛋。 x = 3 ,以及所有形如 3 + 7n 的数,也都是原方程的解。
大家或许已经看到了,我们成功地找到了 24 • x mod 42 = 30 的解,依赖于一个巧合: 24 和 42 的最大公约数 6 ,正好也是 30 的约数。因此,改用“把”作单位重新叙述问题,正好最后的“余 30 个”变成了“余 5 把”,依旧是一个整数。如果原方程是 24 • x mod 42 = 31 的话,我们就没有那么走运了,问题将变成“买多少盒才能让最后数完余 5 又 1/6 把”。这怎么可能呢?我们是整把整把地买,整把整把地数,当然余数也是整把整把的。因此,方程 24 • x mod 42 = 31 显然无解。
综上所述,如果关于 x 的方程 a • x mod n = b 当中的 a 和 n 不互质,那么求出 a 和 n 的最大公约数 d 。如果 b 恰好是 d 的整倍数,那么把方程中的 a 、 n 、 b 全都除以 d ,新的 a 和 n 就互质了,新的 b 也恰好为整数,用扩展的辗转相除求解新方程,得到的解也就是原方程的解。但若 b 不是 d 的整倍数,则方程无解。
**备注:x为a的数量,y为b的数量(x0=1,y0=0);
看题目:
求关于 x 的同余方程 ax ≡ 1 (mod b)的最小正整数解。
输入格式:
输入只有一行,包含两个正整数 a, b,用一个空格隔开。
输出格式:
输出只有一行,包含一个正整数 x0,即最小正整数解。输入数据保证一定有解。
- #include<iostream>
- #include<cstdio>
- using namespace std;
- int gcd(int a,int b,int &x,int &y)
- {
- if(b==){
- x=;
- y=;
- return a;
- }
- int r=gcd(b,a%b,x,y);
- int temp=x;
- x=y;
- y=temp-a/b*y;
- return r;
- }
- void init()
- {
- int a,b,x,y;
- cin>>a>>b;
- gcd(a,b,x,y);
- x=(x%b+b)%b;
- printf("%d",x);
- }
- int main()
- {
- init();
- system("pause");
- return ;
- }
gcd和拓展gcd算法的更多相关文章
- 欧几里德算法gcd及其拓展终极解释
这个困扰了自己好久,终于找到了解释,还有自己改动了一点点,耐心看完一定能加深理解 扩展欧几里德算法-求解不定方程,线性同余方程. 设过s步后两青蛙相遇,则必满足以下等式: (x+m*s)-(y+n ...
- 数学:乘法逆元-拓展GCD
乘法逆元应用在组合数学取模问题中,这里给出的实现不见得好用 给出拓展GCD算法: 扩展欧几里得算法是指对于两个数a,b 一定能找到x,y(均为整数,但不满足一定是正数) 满足x*a+y*b=gcd(a ...
- 礼物(中国剩余定理+拓展gcd求逆元+分治=拓展Lucus)
礼物 题意: 求\[C(n,m)\ \%\ p\] \(n,m,p\le 10^9\),且若\(p=\prod_{i=1}^{k}{p_i}^{c_i}\),则\(\forall i\in [1..k ...
- 欧几里得算法:从证明等式gcd(m, n) = gcd(n, m mod n)对每一对正整数m, n都成立说开去
写诗或者写程序的时候,我们经常要跟欧几里得算法打交道.然而有没要考虑到为什么欧几里得算法是有效且高效的,一些偏激(好吧,请允许我用这个带有浓重个人情感色彩的词汇)的计算机科学家认为,除非程序的正确性在 ...
- iOS边练边学--GCD的基本使用、GCD各种队列、GCD线程间通信、GCD常用函数、GCD迭代以及GCD队列组
一.GCD的基本使用 <1>GCD简介 什么是GCD 全称是Grand Central Dispatch,可译为“牛逼的中枢调度器” 纯C语言,提供了非常多强大的函数 GCD的优势 G ...
- HDU 3613 Best Reward(拓展KMP算法求解)
题目链接: https://cn.vjudge.net/problem/HDU-3613 After an uphill battle, General Li won a great victory. ...
- 拓展KMP算法详解
拓展KMP解决的问题是给两个串S和T,长度分别是n和m,求S的每一个后缀子串与T的最长公共前缀分别是多少,记作extend数组,也就是说extend[i]表示S[i,n-1](i从0开始)和T的最长公 ...
- UVA 1642 Magical GCD(经典gcd)
题意:给你n(n<=100000)个正整数,求一个连续子序列使序列的所有元素的最大公约数与个数乘积最大 题解:我们知道一个原理就是对于n+1个数与n个数的最大公约数要么相等,要么减小并且减小至少 ...
- Solve Equation gcd(x,y)=gcd(x+y,lcm(x,y)) gcd(x,y)=1 => gcd(x*y,x+y)=1
/** 题目:Solve Equation 链接:http://acm.hnust.edu.cn/JudgeOnline/problem.php?id=1643 //最终来源neu oj 2014新生 ...
随机推荐
- jQuery easyui combobox级联及内容联想
1.需求:已有一个下拉框A表示地区,现新增需求,需要在A选择不同地区时,增加一个展示该地区所有城市的下拉框B, 由于城市较多,要求B能实现用户输入和模糊匹配展示功能. 2.实现: (1)首先在A下面把 ...
- 使用Spring MVC统一异常处理
http://blog.csdn.net/ufo2910628/article/details/40399539
- Java数组,去掉重复值、增加、删除数组元素
import java.util.List; import java.util.ArrayList; import java.util.Set; import java.util.HashSet; p ...
- mysql日期类型默认值'0000-00-00'容错处理
mysql日期默认值'0000-00-00'惹的祸 .net连mysql数据库时,如果表里有字段是日期型且值是‘0000-00-00’时,会报错.在C#里面日期不可能是那样的.或许是最小日期定义的差别 ...
- 在使用sqlite时淌过的坑
以前一直用sqlite.net 1.0.66.0版本,在.net4下面程序写好了部署到目的地机器时winform程序总是出现缺少运行时的问题.有时装了运行时也还是出问题,后来发现是混合模式的问题,当时 ...
- 【eoe 6】ActionBar的使用
一. Action Bar 一般位于屏幕顶部,包括四个可操作区域: 应用图标或LOGO区域,用于视图控制的Spinner下拉菜单或TAB控件区域, Action button(也称为Action It ...
- [LeetCode] 桶排序的特殊解,例 Sort Color
Sort Colors Given an array with n objects colored red, white or blue, sort them so that objects of t ...
- centos下配置java环境变量
一. 需要配置的环境变量1. PATH环境变量.作用是指定命令搜索路径,在shell下面执行命令时,它会到PATH变量所指定的路径中查找看是否能找到相应的命令程序.我们需要把 jdk安装目录下的bin ...
- 【struts2】OGNL
1 OGNL概述 OGNL是对象图导航语言Object-Graph Navigation Language的缩写,它是一种功能强大的表达式语言(Expression Language,简称为EL),通 ...
- ruby -- 进阶学习(四)paperclip上传中文命名图片
Paperclip -- 上传中文命名图片 使用Paperclip和ImageMagick插件来处理图片的时候,上传非中文命名的图片时,只要把配置写好就没问题 if you need to ...