乘法逆元之欧几里得和扩展欧几里得

乘法逆元

一、模运算的性质

  • ( a + b ) % p = ( a % p + b % p) % p
  • ( a + b ) % p =( ( a % p + b % p ) % p + p ) % p

注意:此处与上一个不一样,(9-7)%8=(9%8-7%8)%8=-6 ;不是我们要的值,这时要加上p

  • ( a * b ) % p = ( ( a % p ) * ( b % p ) ) % p

二、除法的模运算

1、除法模运算

(a/b)%p=(a%p)/(b%p) ,如果我们保证可以整除,它是否成立呢?

取a=8,b=2,p=6; 左式=4,右式=1;也就是说 除法的模运算不一定成立。

2、解决除法模运算问题

​ 能否将除法转化为乘法?找到 binv ,使得 ( a / b ) % p = = ( a ∗ b i n v ) % p (a/b)\%p==(a*b_{inv})\%p a/b%p==(abinv)%p ;若能,则称 b i n v b_{inv} binv为 b在模p意义下 的乘法逆元 ;


三、乘法逆元

1、定义

​ 若在mod p意义下,对于一个整数a,有 ( a ∗ b ) (a*b)%p=1 (ab),那么这个整数b即为a的 乘法逆元,同时a也为b的乘法逆元。一个数有逆元的充分必要条件是gcd(a,p)=1,此时a才有对p的乘法逆元

2、逆元是干什么的呢

​ 首先对于除法取模不成立,即$ (a/b)%p!=(a%p)/(b%p)$。显然数学家们是不能忍受这种局面的,他们扔出了“逆元”来解决这个问题。因为取模运算对于乘法来说是成立的,逆元就是把除法取模运算转化为乘法取模运算。
( a / b ) % p = m ( 1 ) ( a × x ) % p = m ( 2 ) (a/b)\%p=m (1)\\ (a \times x)\%p=m (2) (a/b)%p=m(1)(a×x)%p=m(2)
(1)模运算对乘法成立,对①式左右两边同时乘以b,得到
a % p = ( m × b ) % p a\%p=(m \times b)\%p a%p=(m×b)%p
(2)如果a和b均小于模数p的话,上式得到:
a = m × b a = m \times b a=m×b
(3)等式两边同时乘以 x x x,联立②式得到:
( a × x ) % p = m % p = ( m × b × x ) % p ( b × x ) % p = 1 (a \times x)\%p = m\%p=(m \times b \times x )\%p \\ (b \times x)\%p = 1 (a×x)%p=m%p=(m×b×x)%p(b×x)%p=1
即x就是b的逆元。(根据逆元的定义可知)总结:求取 ( a / b ) (a/b)%p (a/b)等同于求取 a × ( b 的逆元 ) a \times (b的逆元)%p a×(b的逆元),因此,求模运算的除法问题就转化为求解一个数的逆元问题。


四、求解逆元

求解一个数的逆元有两种方法:费马定理和扩展欧几里得

1、费马小定理

因为在算法竞赛中模数p总是质数,所以可以使用费马小定理。
b p − 1 % p = 1 b^{p-1}\%p=1 bp1%p=1
可以得到 ( b × b p − 2 ) % p = 1 (b \times b^{p-2})\% p=1 (b×bp2)%p=1,所以 b p − 2 b^{p-2} bp2是b在mod p条件下的逆元

public class PowUtil {

    public static Long quickPow(Long a,Long n,Long p){
        //结果
        Long res = 1L;
        while (n != 0) {
            //判断 n 的二进制的最后一位是否为0
            if((n&1)!=0){
                //当n的二进制最后一位为1时,乘以当前的权重
                res = (res*a)%p;
            }
            //更新n,每次n向右移一位
            n = n >> 1;
            //更新每一位的权重
            a = (a*a)%p;
        }
        return res;
    }

}

public class InverseElement {

    /**
     * 利用b^(n-1)%p=1求解b的逆元
     * @param a 质数
     * @param p 模数
     * @return a的逆元
     */
    public static Long inverseElement(Long a,Long p){
        //quickPow()是快速幂函数
        return PowUtil.quickPow(a,p-2,p);
    }

}
2、扩展欧几里得(exgcd)
(1)裴蜀定理

​ 若a,b是整数,且gcd(a,b)=d,那么对于任意的整数x,y,ax+by都一定是d的倍数,特别地,一定存在整数x,y,使ax+by=d成立。它的一个重要推论是:a,b互质的充分必要条件是存在整数x,y使ax+by=1.

(2)exgcd

a x + b y = d = g c d ( a , b ) = g c d ( b , a % b ) = b x 0 + ( a % b ) y 0 因为 a % b = a − a b × b 所以 a x + b y = b x 0 + a % b y 0 = b x 0 + ( a − a / b ∗ b ) y 0 = b x 0 + a y 0 − a / b ∗ y 0 ∗ b = a y 0 + b ( x 0 − a / b ∗ y 0 ) ( 1 ) 由 ( 1 ) 得出: x = y 0 , y = x 0 − ( a / b ) ∗ y 0 \begin{aligned} % requires amsmath; align* for no eq. number ax+by& =d \\& =gcd(a,b)=gcd(b,a\%b)\\ & = bx_0+(a\%b)y_0\\ 因为a\%b& = a-\frac{a}{b}\times b\\ 所以ax+by&=bx_0+a\%by_0\\ &=bx_0+(a-a/b*b)y_0\\ &=bx_0+ay_0-a/b*y_0*b\\ &=ay_0+b(x_0-a/b*y_0)&(1)\\ 由(1)得出:x&=y_0,y=x_0-(a/b)*y_0 \end{aligned} ax+by因为a%b所以ax+by(1)得出:x=d=gcd(a,b)=gcd(b,a%b)=bx0+(a%b)y0=aba×b=bx0+a%by0=bx0+(aa/bb)y0=bx0+ay0a/by0b=ay0+b(x0a/by0)=y0,y=x0(a/b)y0(1)

C++:

//第一种写法
ll Exgcd1(ll a, ll b, ll &x, ll &y) {
      if (!b) {
            x = 1;
            y = 0;
            return a;
      }
      ll d = Exgcd(b, a % b, x, y);
      ll t = x;
      x = y;
      y = t - (a / b) * y;
      return d;
}

//第二种写法
ll Exgcd2(ll a, ll b, ll &x, ll &y) {
      if (!b) {
            x = 1;
            y = 0;
            return a;
      }
      ll d = Exgcd(b, a % b, y, x);
      y = y - (a / b) * x;
      return d;
}

ll niyuan(ll a, ll b)   //求a对b取模的逆元
{
    ll x, y;
    exgcd(a, b, x, y);
    return (x + b) % b;
}

Java:

  • 前提条件求 a x = 1 ( m o d m o d ) ax=1(mod\qquad mod) ax=1(modmod),且 a a a m o d mod mod互质
public class exgcd {
    //扩展欧几里得算法
    public static long x,y; 

    //(d*e)%(p-1)(q-1)=1
    //ax + my = 1(mod m)
    public void exgcd(long a,long b){
        if (b==0) {
            x = 1;
            y = 0;
            return;
        }
        exgcd(b,a%b);
        long xx = x;
        x = y;
        y = xx - (a/b)*y;
    }
}

​ 欧几里得算法只能求解最大公因数,但是扩展的欧几里得算法既可以求出最大公因数,还可以求出 a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b) 的通解 x x x y y y

​ 求解形如 a ∗ x + b ∗ y = c a*x +b*y = c ax+by=c 的通解,但是一般没有谁会无聊到让你写出一串通解出来,都是让你在通解中选出一些特殊的解,比如一个数对于另一个数的乘法逆元。

​ 分析:

  • gcd函数与exgcd函数相比,只是增加了求解x,y的步骤,其余的没变;

  • a ∗ x + b ∗ y = c a*x + b*y = c ax+by=c 有解的充要条件: c % g c d ( a , b ) = = 0 c\% gcd ( a , b )==0 c%gcd(a,b)==0

  • e x g c d ( a , b , x , y ) exgcd(a,b,x,y) exgcd(a,b,x,y) —>利用欧几里得算法不断递归直到 x = 1 , y = 0 x=1,y=0 x=1,y=0—>反向递归求出第一层的 x x x y y y x x x即为 e e e m m m 的逆元。

(3) a x ≡ 1 ( m o d n ) ax\equiv 1(mod\qquad n) ax1(modn)

​ 求解 a ∗ x = 1 ( m o d m ) a*x =1(mod \qquad m) ax=1(modm)中的 x x x ?

​ 这里,我们称 x x x a a a 关于 m m m 的乘法逆元。可以等价于这样的表达式: a ∗ x + m ∗ y = 1 a*x + m*y = 1 ax+my=1,当 g c d ( a , m ) ! = 1 gcd(a , m) != 1 gcd(a,m)!=1 的时候是没有解,这也是 a ∗ x + b ∗ y = c a*x + b*y = c ax+by=c 有解的充要条件: c % g c d ( a , b ) = = 0 c\%gcd(a,b)==0 c%gcd(a,b)==0

​ 利用 e x g c d ( a , b , x , y ) exgcd(a,b,x,y) exgcd(a,b,x,y) 求解 x x x y y y ,然后 ( x + m ) (x+m)%m (x+m) 就是所求结果了。

典型例题:第十届蓝桥杯省赛Java研究生组:试题E:RSA解密


五、参考文献

[1] 乘法逆元超详解

[2]乘法逆元

[3]exgcd知识完善

[4]扩展欧几里得算法(求逆元)总结

[5]拓展欧几里得定理的应用

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值