• 洛谷——P3811 【模板】乘法逆元


    P3811 【模板】乘法逆元

    线性求逆元

    逆元定义:若$a*xequiv1 (mod {b})$,且$a$与$b$互质,那么我们就能定义: $x$为$a$的逆元,记为$a^{-1}$,所以我们也可以称$x$为$a$的倒数,

    所以对于$frac{a}{b} (mod {p})$ ,我们就可以求出$b$在$mod {p}$下的逆元,然后乘上$a$,再$mod {p}$,就是这个乘法逆元的值了。

    一、exgcd求逆元(O(l$og_n$))

    这个就是利用拓欧求解线性同余方程$a*x equiv c (mod {b})$

    的c=1的情况。我们就可以转化为$a*x + b*y = 1$,求解这个方程的解。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    
    #define ll long long
    using namespace std;
    
    void exgcd(ll a,ll b,ll &x,ll &y){
        if(!b){
            x=1,y=0;
            return;
        }
        exgcd(b,a%b,x,y);
        ll tmp=x;
        x=y;
        y=tmp-a/b*y;
    }
    
    int n,p;
    
    int main()
    {
        scanf("%d%d",&n,&p);
        
        for(int i=1;i<=n;i++){
            ll x,y;
            exgcd(i,p,x,y);
            x=(x%p+p)%p;
            printf("%lld
    ",x);
        }
        
        return 0;
    }
    Exgcd

    二、快速幂+费马小定理

    费马小定理:若$p$为素数,$a$为正整数,且$a,p$互质。 则有$a^{p-1} equiv 1 (mod {p})$。

    $a*xequiv 1(mod {b})$

    $a*xequiv a^{p-1} (mod {b})$
    $x equiv a^{p-2} (mod {b})$

    有点儿慢。。。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    
    #define ll long long
    using namespace std;
    
    
    int n,p;
    
    ll pow(int a,int b,int mod){
        ll s=1,t=a%mod;
        for(;b;b>>=1,t=1ll*t*t%mod)
            if(b&1) s=1ll*s*t%mod;
        return s;
    }
    
    int main()
    {
        scanf("%d%d",&n,&p);
        
        for(int i=1;i<=n;i++){
            printf("%lld
    ",pow(i,p-2,p));
        }
        
        return 0;
    }
    快速幂

     

    三、线性递推求逆元

     如何递推呢?

    大佬说:推一下就好了嘛

    蒟蒻(我):。。。=_=

    首先$1^{-1}equiv1(modp)$

    设$p=k imes i+r$,$r < i$,$1< i < p$

    那么$k imes i+r equiv 0 (mod p)$

    方程同乘$i^{-1},r^{-1}$得

    $k imes r^{-1}+i^{-1} equiv 0 (mod p)$

    移项得:$i^{-1}equiv -k imes r^{-1} (mod p)$

    即$i^{-1}equivlfloor{frac{p}{i}} floor imes (p mod i)^{-1} (mod p)$

    也就是下面这一行代码:

    inv[i]=(p-p/i)*inv[p%i]%p;

    奉上代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    
    #define ll long long
    #define N 10101010
    using namespace std;
    
    
    int n,p;
    ll inv[N];
    int main()
    {
        scanf("%d%d",&n,&p);
        inv[1]=1;
        printf("1
    ");
        for(int i=2;i<=n;i++){
            inv[i]=(p-p/i)*inv[p%i]%p;
            printf("%lld
    ",inv[i]);
        }
        return 0;
    }
  • 相关阅读:
    60)模板类去派生新的子类
    linux ssh搭建
    javascript学习6-练习之3二分查找算法
    javascript学习5-练习之2冒泡排序算法
    javascript学习4-练习之1转置矩阵
    javascript学习3-自定义函数
    计算机网络学习1-网络层次
    javascript学习-安全初探之沙箱
    html学习1-html5基础学习
    jquery学习之1.23-ajax使用
  • 原文地址:https://www.cnblogs.com/song-/p/9724555.html
Copyright © 2020-2023  润新知