Gcd&Exgcd算法学习小记
Preface
对于许多数论问题,都需要涉及到Gcd,求解Gcd,常常使用欧几里得算法,以前也只是背下来,没有真正了解并证明过。
对于许多求解问题,可以列出贝祖方程:ax+by=Gcd(a,b),用Exgcd解之即可到答案,Exgcd即扩展欧几里得算法。他还能求乘法逆元,同余方程通解。没有你想得到的,只有你做不到的。
这里是对于两个算法的学习小记
Content
欧几里得算法
算法介绍
由百度百科得
欧几里德算法又称辗转相除法,用于计算两个正整数a,b的最大公约数。
从整数的除法可知:对任给二整数a,b0,必有二整数q及r存在,使得a=qb+r,0≤rb,并且q及r是唯一存在的,这是数论的一条基本定理,整数的一系列重要性质都可以由此得到,如果反复利用这一基本定理,就可以得到因为每进行一次除法,余数就至少减一,而b是有限的正整数,所以最多进行b次,总可以得到一个余数是零的等式,即rn+1=0。
当然,百度说的这种话我都是看不懂的。
其实辗转相除法就是运用了Gcd(a,b)=Gcd(b,a mod b),直到a≡0(mod b),b即为所求。
这个方法的目的是为了达到可以将求解的两个数不断缩小,使得效率为对数级别。
算法证明
那么,我们如何求证这个式子的正确性呢?
我们令
根据模运算的定义,可以有
移项可得
令d为a,b公约数,可有
根据我的思考,得出拥有公约数的两个数相减,其差必定能整除这个公约数,用乘法分配律易证。由这个东东,我们知道d一定是a,kb的公约数,故可得
综上所瞎BB,因为d|b,d|a mod b,所以b和a mod b有公约数d,又因为d为a,b公约数,所以a,b,a mod b都包含约数d
上面的d为任意一个,当d为a,b的最大公约数,根据上面所说,此时b和a mod b一定也包含公约数d
算法实现
自此,我们证了欧几里得几千年前就会证的东西。用现代化语言来描述这古老的知识是这样的
扩展欧几里得算法
算法简介
按照惯例,看看大佬们怎么说。由百度百科得
扩展欧几里得算法是欧几里得算法(又叫辗转相除法)的扩展。除了计算a、b两个整数的最大公约数,此算法还能找到整数x、y(其中一个很可能是负数)。通常谈到最大公因子时, 我们都会提到一个非常基本的事实: 给予二整数 a 与 b, 必存在有整数 x 与 y 使得ax + by = gcd(a,b)。有两个数a,b,对它们进行辗转相除法,可得它们的最大公约数——这是众所周知的。然后,收集辗转相除法中产生的式子,倒回去,可以得到ax+by=gcd(a,b)的整数解。
这篇百度百科用了列式子,作诠释的说明方法,让我明白了许多,表达了作者写时凉凉的心情。
自从会证欧几里得算法之后,这一切的一切变得更加明朗蒙蔽
说白了,扩展欧几里得就是扩展的,运用某些欧几里得算法的东西来解出关于x,y的方程ax+by=gcd(a,b)的通解。但是一般没有几个身体健康的出题人会让你求这个无聊的东西。所以这个东西一般应用于求方程的某个特殊解亦或者求乘法逆元。
算法核心
我们看看它是怎么操作的,显然有
我们令,显然等于我头上的这个式子
我们将上面左式根据模定义升级得到
我们将y′代进括号里,再提取b,得
我们再看看上面的连等式ax+by,他们是等价的,根据恒等定理有
但是我们知道这个有什么用呢?我们又不知道他们其中任何一个值,根本求不出x和y。
我们需要冷静一下,x,y是在ax+by=Gcd(a,b)时的解。x′,y′是在gcd(b,a mod b)=bx′+(a mod b)y′时的解,那么
这既然是扩展的,必定与欧几里得有不可告人的关系。gcd在最后是当gcd(a,0)=a时,求出最大公约数。那么当b=0时,我们带进去ax+by=Gcd(a,b)里面算,其实就是ax=a,那么x必定为1.b不可知,我们可以将b视为0,那么此时x,y的一个解就是
我们既然知道了这个,我们根据上面x,y与x′,y′的关系式,推算出x,y的值,不断递归回去,继而得出满足贝祖方程的一个解。因为这个方程必定有规律可循,所以我们对这个解进行某些变换,即可得出这个方程的通解,这是显然又必然的。
算法实现
实现起来和欧几里得算法有异曲同工之妙,可以说我们比欧几里得厉害,因为他不会编程;
算法扩展
扩展一:乘法逆元
对于形如这个样的式子,我们称x是a关于b的乘法逆元
这个式子的本质就是
脑补得到
如果这个式子有关于x,y的整数解,那么a,b 必定互质。为什么?
如果a,b不互质,那么他们必定有公约数。那么根据上面所说,拥有公约数的两个数相减,其差必定能整除这个公约数,然而1并不是一个大于1的公约数,所以得证。
因为y是未知的,我们可以将y视为相反数,那么符号可以变为正,而扩展gcd又可以解负数,其颜值越来越像贝祖公式了。又因为gcd(a,b)=1,所以得到
一不小心又可以用扩展欧几里得来解了。显然可以求出x的值,x的值即为乘法逆元。对于这种a,b互质的同余方程,一般只有唯一解。当然,会有无解的情况。根据一个定理来判断:ax+by=c,那么gcd(a,b)丨c,不然的话无解。
扩展二:求解方程ax+by=c
这个与上面类似。因为gcd(a,b)丨c,所以我们可以用扩展欧几里得先求出ax+by=gcd(a,b)
如何求目前这个方程的通解?假设我们求出了对于关于x,y的方程ax+by=gcd(a,b)的一组解为x0,y0,我们带入可以得到
ax0+by0=gcd(a,b),继而还有a(x0+b)+b(y0-a),a(x0+2*b)+b(y0-2*a),因为这样乘出来还是ax0+by0,所以可行
所以通解为x=x0+k*b;y=y0-k*a;
我们再看回原来的方程ax+by=c,发现其实类似,可以自己思考。
经典例题
[ZJOI2002] 青蛙的约会 →题解
[Vijos1009] 清帝之惑之康熙 →题解
[NOIP2012] 同余方程 →题解
[poj2115] C Looooops →题解
[poj2891] Strange Way to Express Integers →题解
[hdu1573] X问题 →题解
[hdu3579] Hello Kiki →题解
[poj2142] 天平 The Balance →题解
[poj1091] 跳蚤 →题解
[bzoj2242][SDOI2011]计算器
Gcd&Exgcd算法学习小记的更多相关文章
- gcd && exgcd算法
目录 欧几里德算法与扩展欧几里德算法 1.欧几里德算法 2.扩展欧几里德算法 欧几里德算法与扩展欧几里德算法 1.欧几里德算法 #include<bits/stdc++.h> using ...
- Cipolla算法学习小记
转自:http://blog.csdn.net/doyouseeman/article/details/52033204 简介 Cipolla算法是解决二次剩余强有力的工具,一个脑洞大开的算法. 认真 ...
- Manacher 算法学习小记
概要 一个字符串有多少个回文的字串?最多有 \(O(n^2)\) 级别个.但 Manacher 算法却可以用 \(O(n)\) 的时间复杂度解决这个问题.同时 Manacher 算法实现非常简单. 一 ...
- 二次剩余Cipolla算法学习笔记
对于同余式 \[x^2 \equiv n \pmod p\] 若对于给定的\(n, P\),存在\(x\)满足上面的式子,则乘\(n\)在模\(p\)意义下是二次剩余,否则为非二次剩余 我们需要计算的 ...
- mongodb入门学习小记
Mongodb 简单入门(个人学习小记) 1.安装并注册成服务:(示例) E:\DevTools\mongodb3.2.6\bin>mongod.exe --bind_ip 127.0.0.1 ...
- DSP算法学习-过采样技术
DSP算法学习-过采样技术 彭会锋 2015-04-27 23:23:47 参考论文: 1 http://wr.lib.tsinghua.edu.cn/sites/default/files/1207 ...
- javascript学习小记(一)
大四了,课少了许多,突然之间就不知道学什么啦.整天在宿舍混着日子,很想学习就是感觉没有一点头绪,昨天看了电影激战.这种纠结的情绪让我都有点喘不上气啦!一点要找点事情干了,所以决定找个东西开始学习.那就 ...
- 算法学习之C语言基础
算法学习,先熟悉一下C语言哈!!! #include <conio.h> #include<stdio.h> int main(){ printf(+); getch(); ; ...
- Python之路,Day21 - 常用算法学习
Python之路,Day21 - 常用算法学习 本节内容 算法定义 时间复杂度 空间复杂度 常用算法实例 1.算法定义 算法(Algorithm)是指解题方案的准确而完整的描述,是一系列解决问题的 ...
随机推荐
- 关于C的全局变量
一般来说,不会将全局变量的定义写在头文件中.因为如果多个C源文件都添加了头文件,很容易引起重复定义的问题,这时候一般编译器都会提示.正确的做法是在C源文件中定义一个全局变量,在头文件中加入全局变量的声 ...
- [工具开发] Grafana 报警仪表盘
Grafana 自V4以来加入了报警功能,所有的报警都集中在 Alert List 菜单里,数量多的话,查看起来很不方便.如下图: 为此我制作了一个简单的 Grafana Alert Dashboar ...
- Linux启动activemq失败
第一种情况: 在网上查找错误,通过./activemq console命令可以查看到activemq启动的错误信息,另外在data/activemq.log文件中可以查看到错误日志. java.io. ...
- linux常用命令【原创】
查看文件内容-while: cat 1.txt|while read line;do echo $line;done while read line; do echo $line; done < ...
- JavaScript 事件委托详解
基本概念 事件委托,通俗地来讲,就是把一个元素响应事件(click.keydown......)的函数委托到另一个元素: 一般来讲,会把一个或者一组元素的事件委托到它的父层或者更外层元素上,真正绑定事 ...
- python 列表中[ ]中冒号‘:’的作用
中括号[ ]:用于定义列表或引用列表.数组.字符串及元组中元素位置 list1 = [, ] list2 = [, , , , , , ] print ] print :] 冒号: 用于定义分片. ...
- Centos系统FastDFS搭建与排错
FastDFS中Tracker server主要是负载均衡和调度,Storage server主要是文件存储. 1.1 系统环境 [root@ centos fastdfs]# cat /etc/re ...
- Python爬虫基础之BeautifulSoup
一.BeautifulSoup的基本使用 from bs4 import BeautifulSoup from bs4 import SoupStrainer import re html_doc = ...
- 【原创】大叔经验分享(51)docker报错Exited (137)
docker container启动失败,报错:Exited (137) *** ago,比如 Exited (137) 16 seconds ago 这时通过docker logs查不到任何日志,从 ...
- leveldb(ssdb)性能、使用场景评估
最近有个业务场景存储压力很大,写远远大于读,读也集中在最近写入,想想这不很适合采用leveldb存储么.leveldb的话好像用ssdb比较多,花了两天时间就ssdb简单做下测试,以下总结. ssdb ...