• 乘法逆元 学习总结


    基本都是抄的大神写好的东西,主要作为一个复习,加深印象。

    定义:若整数 b,m 互质,并且 b|a(b整除a),则存在一个整数 x,使得 a/b ≡ a * c (mod m)则称 x 为 b 的模 m 法逆元,记为 b-1(mod m)

    那么我们如何求 b-1(mod m)

    根据定义,a/b ≡ a * b-1 ≡ a/b * b * b-1 (mod m),那么 b * b-1 ≡ 1 (mod m)。

    到这里可以用两种方法求解b-1(mod m)

    1、费马小定理。

      费马小定理:若p是质数,则对于任意整数 a,有 ap ≡ a (mod p)。那么 bp ≡ b (mod p) → b * bp-1 ≡ b (mod p) → b * bp-2 ≡ 1 (mod p)。因此,当模数 p 为质数时,bp-2 即为 b-1(mod p) 。因此我们可以使用快速幂求出逆元。

    int qpow(int i,int k,int mod)
    {
        int res=1;
        while(k)
        {
            if(k&1) res=(LL)res*i%mod;
            i=(LL)i*i%mod;
            k>>=1;
        }
        return res;
    }
    
    int main()
    {
        int invb=qpow(b,p-2,p); //p是质数,b的逆元就是b^(p-2) mod p 
        return 0;
    }

    2、解同余方程。

      因为 b * b-1 ≡ 1 (mod m),那么同余方程 b * x ≡ 1 (mod m) 的解就是逆元,相当于解方程 b * x + m * y = 1,根据扩展欧几里得,只要保证了 b,m 互质,我们就可以用这种方法求出逆元。

    void exgcd(int a,int b,int &x,int &y)
    {
        if(b==0) {x=1;y=0;return;}
        exgcd(b,a%b,x,y);
        int z=x;x=y;y=z-a/b*y;
    }
    
    int main()
    {
        int x,y;
        exgcd(b,p,x,y);
        x=(x%p+p)%p;
        return 0;
    }

    当然还有其他特殊情况我们需要选用特殊的方法来求逆元:

    1、求解 1~n 这样一串连续数的逆元:

      已知 1-1 ≡ 1 (mod p)

      设 p = k * i + r,即 ⌊p/i⌋ = k,p%i = r

      那么 k * i + r ≡ 0 (mod p)

      左右同乘以i-1r-1,得 k * r-1 + i-1 ≡ 0 (mod p)

      移项,得 i-1 ≡ -k * r-1 (mod p)

      因为k = ⌊p/i⌋,r = p%i

      可得,i-1 = -⌊p/i⌋ * (p%i)-1 (mod p)

      为保证逆元为正数,令

      i-1 = (p-⌊p/i⌋) * (p%i)-1 (mod p)

      那么我们就可以利用这个式子递推出 1~n 的逆元。

    int main()
    {
        scanf("%d%d",&n,&p);
        inv[1]=1;
        for(int i=2;i<=n;i++) inv[i]=(LL)(p-p/i)*inv[p%i]%p;
        for(int i=1;i<=n;i++) printf("%d
    ",inv[i]);
        return 0;
    }

    2、求 1~n 的阶乘数的逆元

      因为$dfrac {1}{left( i+1 ight) !} imes left( i+1 ight) =dfrac {1}{i!}$

      设 inv[i] 为 i! 的逆元,那么 inv[i+1] * (i+1) = inv[i]

      利用这个关系我们就可以在知道 inv[n] 的情况下逆推出 1~n 的阶乘的逆元了。

    int qpow(int i,int k,int mod)
    {
        int res=1;
        while(k)
        {
            if(k&1) res=(LL)res*i%mod;
            i=(LL)i*i%mod;
            k>>=1;
        }
        return res;
    }
    
    int main()
    {
        scanf("%d%d",&n,&p);
        fact[0]=1;
        for(int i=1;i<=n;i++) fact[i]=(LL)fact[i-1]*i%p;
        invi[n]=qpow(fact[n],p-2,p);
        for(int i=n-1;i>=1;i--) invi[i]=(LL)invi[i+1]*(i+1)%p;
        return 0;
    }
  • 相关阅读:
    arcpy地理处理工具案例教程-生成范围-自动画框-深度学习样本提取-人工智能-AI
    arcpy地理处理工具案例教程-将细碎图斑按相同属性或相近属性合并相邻图斑
    遥感应用指数整理
    arcpy实例教程-地图图层导出到要素类
    arcpy实例教程-地图范围导出到要素类
    arcpy实例教程-上游流域下游流域查找
    arcgis python脚本工具实例教程—栅格范围提取至多边形要素类
    传统测绘工程和新时代的测绘地理信息工程专业点评
    GIS地理处理脚本案例教程——批量栅格分割-批量栅格裁剪-批量栅格掩膜-深度学习样本批量提取
    excel矩阵运算操作-转置 行列式 相乘 逆阵
  • 原文地址:https://www.cnblogs.com/BakaCirno/p/11515718.html
Copyright © 2020-2023  润新知