数论 - 多种方法求乘法逆元

求乘法逆元的5种方法

求 正 整 数 a 关 于 1 模 p 的 的 乘 法 逆 元 , 即 求 满 足 a x ≡ 1 ( m o d   p ) 的 正 整 数 解 x 。 求正整数a关于1模p的的乘法逆元,即求满足ax≡1(mod\ p)的正整数解x。 a1pax1(mod p)x


一、 扩 展 欧 几 里 得 算 法 ( O ( l o g P ) ) 扩展欧几里得算法(O(logP)) (O(logP))

将 a x ≡ 1 ( m o d   p ) 转 化 为 解 方 程 a x + p y = 1 的 正 整 数 解 x 。 将ax≡1(mod\ p)转化为解方程ax+py=1的正整数解x。 ax1(mod p)ax+py=1x

前 提 条 件 : a 与 p 互 质 , 此 时 解 唯 一 。 前提条件:a与p互质,此时解唯一。 ap

代码:

int exgcd(int a,int b,int &x,int &y)  //ax≡1(mod p)
{                                     //ax+py=1
    if(!b)
    {
        x=1,y=0;
        return a;
    }
    
    int d=exgcd(b,a%b,y,x);
    y-=(a/b)*x;
    
    return d;
}

int main()
{
	int p,x,y;
    p=mod;
    for(int a=1;a<=20;a++)	//求出1~20的逆元
    {
        exgcd(a,p,x,y);
        cout<<(x+p)%p<<endl;
    }
}

二 、 费 马 小 定 理 ( O ( l o g P ) ) 二、费马小定理(O(logP)) (O(logP))

前 提 条 件 : p 为 质 数 前提条件:p为质数 p

则 有 a p − 1 ≡ 1 ( m o d   p ) 则有a^{p-1}≡1(mod\ p) ap11(mod p)

即 a ⋅ a p − 2 ≡ 1 ( m o d   p ) , 即a·a^{p-2}≡1(mod\ p), aap21(mod p)

a p − 2 即 逆 元 。 通 过 快 速 幂 可 解 。 a^{p-2}即逆元。通过快速幂可解。 ap2


三 、 欧 拉 定 理 求 逆 元 ( O ( P ) ) 三、欧拉定理求逆元(O(\sqrt{P})) (O(P ))

欧 拉 定 理 : 若 p , a 为 正 整 数 , 且 p , a 互 质 , 则 : 欧拉定理:若p,a为正整数,且p,a互质,则: p,ap,a:

a ϕ ( p ) ≡ 1 ( m o d   p ) a^{\phi(p)}≡1(mod\ p) aϕ(p)1(mod p)

当 p 为 质 数 时 , 即 费 马 小 定 理 。 当p为质数时,即费马小定理。 p

因 此 , 我 们 可 以 对 p 先 求 出 欧 拉 函 数 ϕ ( p ) , 再 用 快 速 幂 求 出 乘 法 逆 元 为 a ϕ ( p ) − 1 。 因此,我们可以对p先求出欧拉函数\phi(p),再用快速幂求出乘法逆元为a^{\phi(p)-1}。 pϕ(p)aϕ(p)1

可 用 定 义 求 欧 拉 函 数 , 时 间 复 杂 度 O ( p ) 可用定义求欧拉函数,时间复杂度O(\sqrt{p}) O(p )

代码:

ll get_euler(ll C)      //定义求欧拉函数
{
    ll res=C;
    for(int i=2;i<=C/i;i++)
        if(C%i==0)
        {
            while(C%i==0) C/=i;
            res=res/i*(i-1);
        }
            
    if(C>1) res=res/C*(C-1);
    return res;
}

亦 可 用 线 性 筛 筛 出 [ 1 , n ] 内 的 欧 拉 函 数 。 亦可用线性筛筛出[1,n]内的欧拉函数。 线[1,n]


四 、 递 推 四、递推

求 区 间 [ 1 , n ] 的 逆 元 , 时 间 复 杂 度 O ( n ) 。 求区间[1,n]的逆元,时间复杂度O(n)。 [1,n]O(n)

代码:

    int inv[N];
    inv[1]=1;
    for(int i=2;i<=20;i++)
        inv[i]=(long long)(mod-mod/i)*inv[mod%i]%mod;

五 、 递 推 求 阶 乘 逆 元 五、递推求阶乘逆元

先 求 出 n ! 的 逆 元 , 再 倒 序 递 推 。 先求出n!的逆元,再倒序递推。 n!

代码:

void init()
{
    fac[0]=1;
    for(int i=1;i<=n;i++)
        fac[i]=fac[i-1]*i%mod; 
        
    inv[n]=quick_pow(fac[n],mod-2,mod); //求出最大项阶乘的逆元
    for(int i=n-1;i>=0;i--)
        inv[i]=inv[i+1]*(i+1)%mod; //递推得到所有阶乘的逆元
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值