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算法学习小记的更多相关文章

  1. gcd && exgcd算法

    目录 欧几里德算法与扩展欧几里德算法 1.欧几里德算法 2.扩展欧几里德算法 欧几里德算法与扩展欧几里德算法 1.欧几里德算法 #include<bits/stdc++.h> using ...

  2. Cipolla算法学习小记

    转自:http://blog.csdn.net/doyouseeman/article/details/52033204 简介 Cipolla算法是解决二次剩余强有力的工具,一个脑洞大开的算法. 认真 ...

  3. Manacher 算法学习小记

    概要 一个字符串有多少个回文的字串?最多有 \(O(n^2)\) 级别个.但 Manacher 算法却可以用 \(O(n)\) 的时间复杂度解决这个问题.同时 Manacher 算法实现非常简单. 一 ...

  4. 二次剩余Cipolla算法学习笔记

    对于同余式 \[x^2 \equiv n \pmod p\] 若对于给定的\(n, P\),存在\(x\)满足上面的式子,则乘\(n\)在模\(p\)意义下是二次剩余,否则为非二次剩余 我们需要计算的 ...

  5. mongodb入门学习小记

    Mongodb 简单入门(个人学习小记) 1.安装并注册成服务:(示例) E:\DevTools\mongodb3.2.6\bin>mongod.exe --bind_ip 127.0.0.1 ...

  6. DSP算法学习-过采样技术

    DSP算法学习-过采样技术 彭会锋 2015-04-27 23:23:47 参考论文: 1 http://wr.lib.tsinghua.edu.cn/sites/default/files/1207 ...

  7. javascript学习小记(一)

    大四了,课少了许多,突然之间就不知道学什么啦.整天在宿舍混着日子,很想学习就是感觉没有一点头绪,昨天看了电影激战.这种纠结的情绪让我都有点喘不上气啦!一点要找点事情干了,所以决定找个东西开始学习.那就 ...

  8. 算法学习之C语言基础

    算法学习,先熟悉一下C语言哈!!! #include <conio.h> #include<stdio.h> int main(){ printf(+); getch(); ; ...

  9. Python之路,Day21 - 常用算法学习

    Python之路,Day21 - 常用算法学习   本节内容 算法定义 时间复杂度 空间复杂度 常用算法实例 1.算法定义 算法(Algorithm)是指解题方案的准确而完整的描述,是一系列解决问题的 ...

随机推荐

  1. 关于C的全局变量

    一般来说,不会将全局变量的定义写在头文件中.因为如果多个C源文件都添加了头文件,很容易引起重复定义的问题,这时候一般编译器都会提示.正确的做法是在C源文件中定义一个全局变量,在头文件中加入全局变量的声 ...

  2. [工具开发] Grafana 报警仪表盘

    Grafana 自V4以来加入了报警功能,所有的报警都集中在 Alert List 菜单里,数量多的话,查看起来很不方便.如下图: 为此我制作了一个简单的 Grafana Alert Dashboar ...

  3. Linux启动activemq失败

    第一种情况: 在网上查找错误,通过./activemq console命令可以查看到activemq启动的错误信息,另外在data/activemq.log文件中可以查看到错误日志. java.io. ...

  4. linux常用命令【原创】

    查看文件内容-while: cat 1.txt|while read line;do echo $line;done while read line; do echo $line; done < ...

  5. JavaScript 事件委托详解

    基本概念 事件委托,通俗地来讲,就是把一个元素响应事件(click.keydown......)的函数委托到另一个元素: 一般来讲,会把一个或者一组元素的事件委托到它的父层或者更外层元素上,真正绑定事 ...

  6. python 列表中[ ]中冒号‘:’的作用

    中括号[ ]:用于定义列表或引用列表.数组.字符串及元组中元素位置 list1 = [, ] list2 = [, , , , , , ] print ] print :]   冒号: 用于定义分片. ...

  7. Centos系统FastDFS搭建与排错

    FastDFS中Tracker server主要是负载均衡和调度,Storage server主要是文件存储. 1.1 系统环境 [root@ centos fastdfs]# cat /etc/re ...

  8. Python爬虫基础之BeautifulSoup

    一.BeautifulSoup的基本使用 from bs4 import BeautifulSoup from bs4 import SoupStrainer import re html_doc = ...

  9. 【原创】大叔经验分享(51)docker报错Exited (137)

    docker container启动失败,报错:Exited (137) *** ago,比如 Exited (137) 16 seconds ago 这时通过docker logs查不到任何日志,从 ...

  10. leveldb(ssdb)性能、使用场景评估

    最近有个业务场景存储压力很大,写远远大于读,读也集中在最近写入,想想这不很适合采用leveldb存储么.leveldb的话好像用ssdb比较多,花了两天时间就ssdb简单做下测试,以下总结. ssdb ...