扩展欧几里得算法详解(exgcd)
一、前言
本博客适合已经学会欧几里得算法的人食用~~~
二、扩展欧几里得算法
为了更好的理解扩展欧几里得算法,首先你要知道一个叫做贝祖定理的玄学定理: 即如果a、b是整数,那么一定存在整数x、y使得$ax+by=gcd(a,b)$。
通俗的说就是:如果$ax+by=c$有解,那么$c\%gcd(a,b)=0$
扩展欧几里得算法就是来求解$ax+by=c$这个方程的(判断有无解仅需使用欧几里得算法即可)。
我们不妨从递归到底的情况来入手。
当$b==0$时,显然有:
$\begin{cases}x=1\\y=0\end{cases}$
为一组合法解
问题是如何解决不是递归最底层的情况。
考虑往下递归时候的操作,不妨设本层的$a$为$a_1$,$b$为$b_1$下一层的$a$为$a_2$,$b$为$b_2$
结合gcd的递归过程,显然有$a_2=b_1,b_2=a_1\%b_1$
由于递归算法总是先get到下层的解,因此我们可以直接设$a_2x_2+b_2y_2=gcd(a_2,b_2)$的解为$x_2,y_2$
然后我们来思考如何根据下层解得到上层的解。
考虑取余运算的性质:显然有:$a\%b=a-(\lfloor a\div b\rfloor)*b$
然后我们把这个结论套进刚刚的式子中,用$a_1$和$b_1$替换$a_2$和$b_2$,这个过程大概是这个样子的:
$a_2x_2+b_2y_2=gcd(a_2,b_2)\\=>b_1x_2+(a_1\%b_1)y_2=gcd(a_2,b_2)\\=>b_1x_2+(a_1-a_1\div b_1*b_1)y_2=gcd(a_2,b_2)\\=>b_1x_2+a_1y_2-(a_1\div b_1)b_1y_2=gcd(a_2,b_2)\\=>a_1y_2+b_1(x_2-a_1\div b_1*y_2)=gcd(a_2,b_2)$
经过以上非常基础的推算,我们可以得到$a_1,b_1,x_1,y_1,x_2,y_2$如下的关系:
$\begin{cases}x_1=y_2\\y_1=x_2-a_1\div b_1*y_2\end{cases}$
于是递归计算即可。
exgcd的代码实现大概长这样:
void exgcd(int a,int b,int &x,int &y)
{
if(b==)
{
x=;y=;
return;
}
exgcd(b,a%b,x,y);
int x1=x,y1=y;
x=y1;y=x1-a/b*y1;
}
exgcd代码实现
三、例题分析
这道题开门见山,直接就说出了要求什么,可谓NOIP茫茫毒瘤题中一股清流
我们要求的是$ax≡1 (mod b)$,不妨设$ax+by=1$,接下来我们就可以搬出我们的exgcd的模板,轻松秒掉这道题。
值得注意的是,我们求出来的是最小解,而题目要求的是最小正整数解,因此如果不符合条件的话还要往上累加。
#include<iostream>
#include<cstdio>
#define int long long
using namespace std;
int x,y,a,b;
void exgcd(int a,int b,int &x,int &y)
{
if(b==)
{
x=;y=;
return;
}
exgcd(b,a%b,x,y);
int x1=x,y1=y;
x=y1;y=x1-a/b*y1;
}
signed main()
{
cin>>a>>b;
exgcd(a,b,x,y);
while(x<)x=(x+b)%b;
cout<<x<<endl;
return ;
}
洛谷P1082同余方程
(贝祖定理内容部分来自这位大佬的博客)
扩展欧几里得算法详解(exgcd)的更多相关文章
- 欧几里得算法与扩展欧几里得算法_C++
先感谢参考文献:http://www.cnblogs.com/frog112111/archive/2012/08/19/2646012.html 注:以下讨论的数均为整数 一.欧几里得算法(重点是证 ...
- 详解扩展欧几里得算法(扩展GCD)
浅谈扩展欧几里得(扩展GCD)算法 本篇随笔讲解信息学奥林匹克竞赛中数论部分的扩展欧几里得算法.为了更好的阅读本篇随笔,读者最好拥有不低于初中二年级(这是经过慎重考虑所评定的等级)的数学素养.并且已经 ...
- 浅谈扩展欧几里得算法(exgcd)
在讲解扩展欧几里得之前我们先回顾下辗转相除法: \(gcd(a,b)=gcd(b,a\%b)\)当a%b==0的时候b即为所求最大公约数 好了切入正题: 简单地来说exgcd函数求解的是\(ax+by ...
- gcd(欧几里得算法)与exgcd(扩展欧几里得算法)
欧几里得算法: 1.定义:gcd的意思是最大公约数,通常用扩展欧几里得算法求 原理:gcd(a, b)=gcd(b, a%b) 2.证明: 令d=gcd(a, b) => a=m*d,b=n ...
- 扩展欧几里得算法(EXGCD)学习笔记
0.前言 相信大家对于欧几里得算法都已经很熟悉了.再学习数论的过程中,我们会用到扩展欧几里得算法(exgcd),大家一定也了解过.这是本蒟蒻在学习扩展欧几里得算法过程中的思考与探索过程. 1.Bézo ...
- 模板——扩展欧几里得算法(求ax+by=gcd的解)
Bryce1010模板 /**** *扩展欧几里得算法 *返回d=gcd(a,b),和对应等式ax+by=d中的x,y */ long long extend_gcd(long long a,long ...
- vijos1009:扩展欧几里得算法
1009:数论 扩展欧几里得算法 其实自己对扩展欧几里得算法一直很不熟悉...应该是因为之前不太理解的缘故吧这次再次思考,回看了某位大神的推导以及某位大神的模板应该算是有所领悟了 首先根据题意:L1= ...
- 『扩展欧几里得算法 Extended Euclid』
Euclid算法(gcd) 在学习扩展欧几里得算法之前,当然要复习一下欧几里得算法啦. 众所周知,欧几里得算法又称gcd算法,辗转相除法,可以在\(O(log_2b)\)时间内求解\((a,b)\)( ...
- 【learning】 扩展欧几里得算法(扩展gcd)和乘法逆元
有这样的问题: 给你两个整数数$(a,b)$,问你整数$x$和$y$分别取多少时,有$ax+by=gcd(x,y)$,其中$gcd(x,y)$表示$x$和$y$的最大公约数. 数据范围$a,b≤10^ ...
随机推荐
- python 使用wxpy实现获取微信好友列表 头像 群成员
最近在学习 python 突然想要试试能不能把微信里面的微信群和好友取出来 结果百度了一下 找到了 wxpy 这怎么能不试一下呢 用到 wxpy.threading.os.time 四个库 第一步 判 ...
- Flask之 请求,应用 上下文源码解析
什么是上下文? 每一段程序都有很多外部变量.只有像Add这种简单的函数才是没有外部变量的.一旦你的一段程序有了外部变量,这段程序就不完整,不能独立运行.你为了使他们运行,就要给所有的外部变量一个一个写 ...
- [洛谷P4823] TJOI2013 拯救小矮人
问题描述 一群小矮人掉进了一个很深的陷阱里,由于太矮爬不上来,于是他们决定搭一个人梯.即:一个小矮人站在另一小矮人的 肩膀上,知道最顶端的小矮人伸直胳膊可以碰到陷阱口. 对于每一个小矮人,我们知道他从 ...
- HBase设计规范(转载)
在这里讲什么设计规范实在是有些不知天高地厚,毕竟笔者本人也只是一个大数据技术的初学者,断然不敢制订什么设计规范的,所以请原谅我的狂妄,这个设计规范,只是本人对自己制订的,与别人无关. 之前,HBase ...
- LeetCode--059--螺旋矩阵 II(python)
效率超级低,但是能过.... class Solution: def generateMatrix(self, n): tR = tC = 0 dR = n-1 dC = n-1 x = [[0 fo ...
- delphi 10.3.1 android沉浸式透明状态栏
从10.2升级上来, 之前的沉浸状态栏在android手机上不透明了, 添加二个发布文件,remote path分别设为 res\values-v21和 res\values-v19 style.xm ...
- Delphi 2010 secondsBetween Bug
在设置定时任务时,无意之间发现一个BUG, 定时在00:10:00的任务,执行了2次, 百思不得其解, 一调试发现, 00:10:00,00:09:59的secondsBetween结果值是0, 正确 ...
- Linux GDB 程序调试工具使用详解
转自 http://www.codeceo.com/article/linux-gdb-tools.html 整理的挺全的 GDB概述 GDB是GNU开源组织发布的一个强大的UNIX下的程序调试 ...
- R语言预测实战(第二章--预测方法论)
2.1预测流程 从确定预测主题开始,一次进行数据收集.选择方法.分析规律.建立模型.评估效果直到发布模型. 2.2.1确定主题 (1)指标:表达的是数量特征,预测的结果也通常是通过指标的取值来体现. ...
- 记一下今天上下班学的Thread
1 Thread 默认为前台线程,即主程序退出后,线程还可以继续(曾经就掉入这个坑中,使用两线程分别进行UDP收发,结果发线程结束了退出方法,收线程还在继续) 2 Thread 没有可以暂停,可以重新 ...