zoukankan      html  css  js  c++  java
  • 『数论』乘法逆元

    在求解除法取模问题((a div b) mod m)时,我们可以转化为([a mod (b imes m)]div b)

    但是如果(b)很大,则会出现爆精度问题,所以我们避免使用除法直接计算。

    可以使用逆元将除法转换为乘法:假设(b)存在乘法逆元,即与(m)互质(充要条件)。

    (c)(b)的逆元,即(b imes c≡1(mod m))

    那么有(adiv b=(adiv b) imes 1=(adiv b) imes b imes c=a imes c(mod m))

    除以一个数取模等于乘以这个数的逆元取模

    • 逆元求解一般利用扩欧。
    • (m)为质数的时候直接使用费马小定理,(m)非质数使用欧拉函数。
    • (m)为质数的时候,神奇的线性方法。

    扩展欧几里得算法

    要求(a,m)互素,存在唯一解。

    int extgcd(int a, int b, int &x, int &y) {
        int d=a;
        if (b!=0) {
            d=extgcd(b,a%b,y,x);
            y-=(a/b)*x;
        }
        else {
            x=1;
            y=0;
        }
        return d;
    }
    int mod_inverse(int a, int m) {
        int x, y;
        extgcd(a, m, x, y);
        return (m+x%m)%m;
    }
    

    费马小定理

    (p)是素数的情况下,对任意整数(x)都有(x^{p}≡x(mod p))

    如果(x)无法被(p)整除,则有(x^{p}-1≡1(mod p))

    可以在(p)为素数的情况下求出一个数的逆元,(x imes x^{p}-2≡1(mod p))(x^{p}-2)即为(x)的逆元。

    LL mul(LL a, LL n) {//求a ^ n % mod
        LL s=1;
        while (n) {
            if (n&1) s=s*a%mod;
            a=a*a%mod;
            n>>=1;
        }
        return s;
    }
    //mul(a, n-2);
    

    欧拉函数

    (phi(m))表示小于等于(m)且与(m)互素的正整数的个数。

    如果(x)(m)互质,则有(xphi (m)≡1(mod m)),即(x imes xphi (m)-1≡1(mod m))(x^{phi(m)-1})(x)的逆元。

    (m)为质数的情况下,(phi (m)=m-1),即为费马小定理。

    思路:

    求出欧拉函数的值,利用欧拉函数的积性性质

    对于任意整数(n),可以将它分解(n=p_{k1} imes p_{k2} imes p_{k3} imes cdots imes p_{km}),其中(p_{i})为质数,(phi(n)=phi(p_{k1}) imes phi(p_{k2}) imes cdots phi(p_{km}))

    最后转化为(phi(n)=n imes prod(p_{i}-1) div p_{i})

    对给定(n)进行整数分解,时间复杂度(O(n)​)

    int eurler_phi(int n) {
        int res=n;
        for (int i=2; i*i<=n; i++) {
            if (n%i==0) {
                res=res/i*(i-1);
                while (n%i==0) n/=i;
            }
        }
        if (n!=1) res=res/n*(n-1);
        return res;
    }
    

    埃氏筛法求欧拉函数值的表,每次发现质因子就把他的倍数的欧拉函数乘上((p-1) imes p)

    (n)为奇数时,有(phi(2 imes n)=phi(n))

    因为(2 imes n)是偶数,偶数与偶数一定不互素,所以只考虑(2n) 与小于它的奇数互素的情况,则恰好就等于(n)的欧拉函数值。

    int euler[maxn];
    void euler_phi2() {
        for (int i=0; i<maxn; i++)
            euler[i]=i;
        for (int i=2; i<maxn; i++)
            if (euler[i]==i)
                for (int j=i; j<maxn; j+=i)
                    euler[j]=euler[j]/i*(i-1);
    }
    

    线性时间求所有逆元

    规定(p)为质数,且(1^{-1}≡1(mod p))

    (p=k imes a+b(b<a,1<a<p)),即(k imes a+b≡0(mod p))

    两边同时乘以(a^{-1} imes b^{-1}),得到

    (k imes b^{-1}+a^{-1}≡0(mod p))

    (a^{-1}≡-k imes b-1(mod p))

    (a^{-1}≡-pdiv a×(pmod a)^{-1}(mod p))

    从头开始扫一遍即可,时间复杂度(O(n))

    int inv[maxn];
    inv[1]=1;
    for (int i=2; i<maxn; i++)
        inv[i]=(p-p/i)%p*inv[p%i];
    
  • 相关阅读:
    第150天:网页中插入百度地图方法(需要密钥)
    第149天:javascript中this的指向详解
    第148天:js+rem动态计算font-size的大小,适配各种手机设备
    第147天:web前端开发中的各种居中总结
    第146天:移动H5前端性能优化
    第145天:jQuery.touchSlider触屏满屏左右滚动幻灯片
    第144天:PS切图方法总结
    第143天:渐进增强和优雅降级之间的不同
    第142天:Size Marks下载安装和使用方法
    第141天:前端开发中浏览器兼容性问题总结(二)
  • 原文地址:https://www.cnblogs.com/shenxiaohuang/p/10162141.html
Copyright © 2011-2022 走看看