【learning】 扩展欧几里得算法(扩展gcd)和乘法逆元
有这样的问题:
给你两个整数数(a,b),问你整数x和y分别取多少时,有ax+by=gcd(x,y),其中gcd(x,y)表示x和y的最大公约数。
数据范围a,b≤1018。
求解这个问题有一种方法,叫做扩展欧几里得算法(简称扩欧),其本质是一个递归求解的过程。
首先由一个前置的结论是gcd(x,y)=gcd(y,x%y)。此处的%为c++中取模操作,下同。
我们不妨设a>b
当a≠0,b=0时,则显然有x=1,y=0。此时gcd(a,b)=a。
当b≠0时,我们假设我们已经求出了bx′+(b%a)y′=gcd(a,b)的x′和y′(这是式1),我们现在要求的是ax+by=gcd(a,b)。
我们对式子1做一些微小的变式
原式=bx′+(b%a)y′
=bx′+(a−⌊ab⌋×b)×y′
=bx′+ay′−⌊ab⌋×b×y′
=ay′+b(x′−⌊ab⌋y′)
不难发现,x=y′,y=(x′−⌊ab⌋y′)就是一组符合条件的解。
然后无脑递归解决即可,代码很短,复杂度显然是O(log2a)的。
1 void exgcd(int a,int b,int &x,int &y){ 2 if(!b) {x=1; y=0; return;} 3 exgcd(b,a%b,y,x); 4 y-=a/b*x; 5 }
下面来说下这东西能干啥
我们不难发现,我们需要求a在模b意义下的乘法逆元(前提条件,a与b互质)
我们可以执行一次exgcd(a,b,x,y),然后x就是a在模b意义下的逆元。
证明显然:
ax+by=1
ax≡1(modb)
当模数不是质数的时候你就会知道这东西有多重要。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!