最近经常会遇到RSA的题目,都会用到扩展欧几里得算法来求逆元,所以去系统的学习了一下这个算法的原理。 先奉上dalao的博客 https://blog.sengxian.com/algorithms/gcd-extgcd
前置说明
a | b 表示:a可以整除b
用途
扩展欧几里得算法是用来求解方程 a x + b y = c ( a , b , c ∈ Z ) ax + by = c (a,b,c \in Z) ax+by=c(a,b,c∈Z)的
可解条件
g c d ( a , b ) ∣ c gcd(a, b) | c gcd(a,b)∣c
实现
记 exgcd(a, b, x, y) 为求解方程 a x + b y = g c d ( a , b ) ax + by = gcd(a,b) ax+by=gcd(a,b) 的函数
先考虑边界情况: 当b = 0时,有 ax = gcd(a, 0) 解得 { x = 1 y = 0 \left\{\begin{aligned}x&=1\\y&=0\end{aligned}\right. {xy=1=0 对于一般情况,设 a ′ = a a^{'} = a a′=a, b ′ = a % b b^{'} = a \% b b′=a%b 则有: a ′ x ′ + b ′ y ′ = g c d ( a ′ , b ′ ) = g c d ( b , a % b ) a^{'} x^{'} + b^{'} y^{'}=gcd(a^{'}, b^{'}) =gcd(b, a\%b) a′x′+b′y′=gcd(a′,b′)=gcd(b,a%b)
恒定条件: g c d ( a , b ) = g c d ( b , a % b ) gcd(a,b) = gcd(b, a\%b) gcd(a,b)=gcd(b,a%b)
又有: g c d ( a , b ) = a x + b y gcd(a, b) = ax+by gcd(a,b)=ax+by 所以有: a x + b y = a ′ x ′ + b ′ y ′ ax+by = a^{'} x^{'} + b^{'} y^{'} ax+by=a′x′+b′y′ a ′ x ′ + b ′ y ′ = b x ′ + ( a % b ) y ′ = b x ′ + ( a − └ a b ┘ b ) y ′ = a y ′ + b ( x ′ − └ a b ┘ y ′ ) a^{'} x^{'} + b^{'} y^{'} = bx^{'}+(a\%b)y^{'}=bx^{'}+(a-\llcorner\frac{a}{b}\lrcorner b)y^{'}=ay^{'}+b(x^{'}-\llcorner\frac{a}{b}\lrcorner y^{'}) a′x′+b′y′=bx′+(a%b)y′=bx′+(a−└ba┘b)y′=ay′+b(x′−└ba┘y′) a x + b y = a y ′ + b ( x ′ − └ a b ┘ y ′ ) ax+by = ay^{'}+b(x^{'}-\llcorner\frac{a}{b}\lrcorner y^{'}) ax+by=ay′+b(x′−└ba┘y′) 所以在迭代过程中有: { x = y ′ y = x ′ − └ a b ┘ y ′ \left\{\begin{aligned}x&=y^{'}\\y&=x^{'}-\llcorner\frac{a}{b}\lrcorner y^{'}\end{aligned}\right. ⎩⎨⎧xy=y′=x′−└ba┘y′
至此扩展欧几里得算法的过程结束,那么这东西跟求逆元有什么关系呢? 对于一个整数x,其逆元 x ′ x^{'} x′需要满足: x x ′ ≡ 1 ( % b ) xx^{'} \equiv1(\%b) xx′≡1(%b) 那么一定存在: x x ′ = k b + 1 xx^{'} = kb+1 xx′=kb+1 将该方程转化为: a x − k b = 1 ax-kb=1 ax−kb=1 再令 y = − k y=-k y=−k 转化为: a x + b y = 1 ax+by=1 ax+by=1 则该方程的解x即为我们要求的逆元
def exgcd(a, b): if b == 0: return 1, 0, a x, y, gcd = exgcd(b, a % b) return y, x - a // b * y, gcd def get_inv(a, b): x, y, gcd = exgcd(a, b) if gcd == 1: return (x % b + b) % b else: raise Exception("不存在逆元")