乘法逆元学习笔记

乘法逆元

例题1

小凯的数字

一串数字l(l+1)(l+2)…(r-1)r,例如l=2,r=5,数字为2345,小凯很喜欢数字9,所以写下的数字除以9的余数是多少

2345 = 2 × 1 0 3 + 3 × 1 0 2 + 4 × 1 0 1 + 5 × 1 0 0 ∀ x ≧ 0 , 1 0 x m o d    9 = 1 ( 2 × 1 0 3 ) % 9 = ( 2 % 9 × 1 0 3 % 9 ) % 9 = 2 % 9 = 2 2345 % 9 = ( 2 × 1 0 3 + 3 × 1 0 2 + 4 × 1 0 1 + 5 × 1 0 0 ) % 9 = ( 2 + 3 + 4 + 5 ) % 9 = 5 ∴ a n s w e r = [ l + ( l + 1 ) + . . . + ( r − 1 ) + r ] % 9 = ( l + r ) ( r − l + 1 ) 2 % 9 2345=2\times 10^3+3\times 10^2+4\times 10^1+5\times 10^0\\ \forall x \geqq 0,10^x\mod 9=1\\ (2\times 10^3)\%9=(2\%9\times 10^3\%9)\%9=2\%9=2\\ 2345\%9=(2\times 10^3+3\times 10^2+4\times 10^1+5\times 10^0)\%9=(2+3+4+5)\%9=5\\ \therefore answer=[l+(l+1)+...+(r-1)+r]\%9=\frac{(l+r)(r-l+1)}{2}\%9 2345=2×103+3×102+4×101+5×100x0,10xmod9=1(2×103)%9=(2%9×103%9)%9=2%9=22345%9=(2×103+3×102+4×101+5×100)%9=(2+3+4+5)%9=5answer=[l+(l+1)+...+(r1)+r]%9=2(l+r)(rl+1)%9

因为模运算必须是整数,上面的 ( l + r ) ( r − l + 1 ) (l+r)(r-l+1) (l+r)(rl+1)可以用整数计算,除以2就不一定还是整数了。

那么分数在模意义下该怎么表示呢?也就是说在mod p意义下,能不能表示 1 a \frac{1}{a} a1呢?

在实数意义下,对于任意的 a ≠ 0 a\neq 0 a=0,都有 a × 1 a = 1 a\times \frac{1}{a}=1 a×a1=1,所以在模意义下,也希望1/a也满足同样的性质: a × 1 a ≡ 1 ( m o d    p ) a\times \frac{1}{a}\equiv 1(\mod p) a×a11(modp),也就是说,尝试找到一个整数,满足 a × x ≡ 1 ( m o d    p ) a\times x\equiv 1(\mod p) a×x1(modp)

定义

a × x ≡ 1 ( m o d    p ) a\times x\equiv1(\mod p) a×x1(modp),则称x为a在模p意义下的乘法逆元,记为 a − 1 ( m o d    p ) a^{-1}(\mod p) a1(modp)

在本章种,模意义下的乘法逆元,简称为逆元。
2 × 5 m o d    9 = 10 m o d    9 = 1 ∴ 5 是 2 关于模 9 的逆元 也就是说, 1 2 在模 9 的意义下可以用 5 来表示 8 × 1 2 = 4 8 × 5 m o d    9 = 40 m o d    9 = 4 2\times 5\mod 9=10\mod 9=1\\ \therefore 5是2关于模9的逆元\\ 也就是说,\frac{1}{2}在模9的意义下可以用5来表示\\\\ 8\times \frac{1}{2}=4\\ 8\times 5\mod 9=40\mod 9=4\\ 2×5mod9=10mod9=152关于模9的逆元也就是说,21在模9的意义下可以用5来表示8×21=48×5mod9=40mod9=4
所以这题只需要求出 5 ( l + r ) ( r − l + 1 ) m o d    9 5(l+r)(r-l+1)\mod9 5(l+r)(rl+1)mod9 为了降低处理的数量级,可以 5 ( l + r ) % 9 ( r − l + 1 ) % 9 m o d    9 5(l+r)\%9(r-l+1)\%9\mod9 5(l+r)%9(rl+1)%9mod9

#include <bits/stdc++.h>
using namespace std;
int t;
long long l,r,ans;
int main()
{
	cin>>t;
    while(t--){
        cin>>l>>r;
        ans=((l+r)%9*(r-l+1)%9*5)%9;
        cout<<ans<<endl;
    }
	return 0;
}

接下来,就从两种不同的方法给定一组a,p,求出a在模p意义下的逆元

方法1

拓展欧几里得算法

a × x ≡ 1 ( m o d    p ) a\times x\equiv1(\mod p) a×x1(modp)入手,等价于 ∃ y , a x + p y = 1 \exists y,ax+py=1 y,ax+py=1等价。实际上就是一个关于a,p的不定方程,就可以用拓展欧几里得算法来解决

并且由裴蜀定理,可以发现存在a在模p意义下的逆元当且仅当gcd(a,p)=1,a和p互质,即 a ⊥ p a\perp p ap

int inv(int a,int p){		//用exgcd求逆元
    int x,y;
    exgcd(a,p,x,y);
    //求不定方程ax+py=1的一组解
    return x;
    //求出的x就是a在模p的意义下的乘法逆元
}

方法2

费马小定理

若p为质数,且a不是p的倍数,则 a p − 1 ≡ 1 ( m o d    p ) a^{p-1}\equiv1(\mod p) ap11(modp)

假设p为质数,那么如果a不是p的倍数,就有 a × a p − 2 = a p − 1 ≡ 1 ( m o d    p ) a\times a^{p-2}=a^{p-1}\equiv 1(\mod p) a×ap2=ap11(modp)

所以a在模p意义下的逆元就是 a p − 2 a^{p-2} ap2,可以用快速幂来解决。

如果a是p的倍数的话,对于任意x,ax也一定是p的倍数,不可能在模p的意义下等于1,也就不存在逆元了

int inv(int a,int p){	//用费马小定理求逆元
    return pow(a,p-2,p);
    //求出a^(p-2)mod p的值
}

不管什么方法,都可以求出一个a在模p的意义下的逆元

定理

在大于等于0,小于p的范围内,模p的逆元(若存在)是唯一的
假设 ∃ 0 ≤ x 1 < x 2 < p , a x 1 ≡ a x 2 ≡ 1 ( m o d    p ) 那么 a ( x 2 − x 1 ) ≡ 0 ( m o d    p ) ∴ a ( x 2 − x 1 ) 是 p 的倍数 又 ∵ a ⊥ p ∴ x 2 − x 1 是 p 的倍数 ∵ 0 < x 2 − x 1 < p ∴ x 2 − x 1 不是 p 的倍数,矛盾 假设\exists 0\leq x_1<x_2<p,ax_1\equiv ax_2\equiv 1(\mod p)\\ 那么a(x_2-x_1)\equiv 0(\mod p)\\ \therefore a(x_2-x_1)是p的倍数\\ 又\because a\perp p\\ \therefore x_2-x_1是p的倍数\\ \because 0<x_2-x_1<p\\ \therefore x_2-x_1不是p的倍数,矛盾 假设∃0x1<x2<pax1ax21(modp)那么a(x2x1)0(modp)a(x2x1)p的倍数apx2x1p的倍数0<x2x1<px2x1不是p的倍数,矛盾

例题2

乘法逆元(线性时间)

给定n,q,求1~n中所有整数在模p意义下的乘法逆元

递推

假设已经知道了 1 到 i − 1 的逆元,现在要求 i 的逆元 初始情况 : 当 i = 1 时, i − 1 ≡ 1 ( m o d    p ) 2 ≤ i < p 时 p = p / i × i + p % i 同余式 : p / i × i + p m o d    i ≡ 0 ( m o d    p ) ∵ p 为质数, 0 < p m o d    i < i ∴ i 和 p m o d    i 的逆元一定存在 在等式两边同时乘以 i − 1 ( p m o d    i ) − 1 ( p m o d    i ) − 1 × p / i + i − 1 ≡ 0 ( m o d    p ) i − 1 ≡ − ( p m o d    i ) − 1 × p / l ( m o d    p ) 假设已经知道了1到i-1的逆元,现在要求i的逆元\\ 初始情况:当i=1时,i^{-1}\equiv 1(\mod p)\\ 2\leq i<p时\\ p=p/i\times i+p\%i\\ 同余式:p/i\times i+p\mod i\equiv0(\mod p)\\ \because p为质数,0<p\mod i<i\\ \therefore i和p\mod i的逆元一定存在\\ 在等式两边同时乘以i^{-1}(p\mod i)^{-1}\\ (p\mod i)^{-1}\times p/i+i^{-1}\equiv0(\mod p)\\ i^{-1}\equiv-(p\mod i)^{-1}\times p/l(\mod p) 假设已经知道了1i1的逆元,现在要求i的逆元初始情况:i=1时,i11(modp)2i<pp=p/i×i+p%i同余式:p/i×i+pmodi0(modp)p为质数,0<pmodi<iipmodi的逆元一定存在在等式两边同时乘以i1(pmodi)1(pmodi)1×p/i+i10(modp)i1(pmodi)1×p/l(modp)

#include <bits/stdc++.h>
using namespace std;
int n,p;
long long inv[3000010];
int main()
{
	scanf("%d%d",&n,&p);
    inv[1]=1;
    //递推初始化
    for(int i=2;i<=n;i++)
        inv[i]=(p-inv[p%i]*(p/i)%p);
    //i^(-1)=p-(p%i)^(-1)*(p/i)%p
    for(int i=1;i<=n;i++)
        printf("%lld\n",inv[i]);
    return 0;
}
//卡cin、cout

倒推

直接倒推可能会比较困难,但是我们知道 1 k = ( k − 1 ) ! k ! \frac{1}{k}=\frac{(k-1)!}{k!} k1=k!(k1)!,所以加入我们已经知道了1!,2!,…,n!mod p的结果,

并且已经知道了1!,2!,…,n!的逆元,就可以知道1到n的逆元了
1. 用循环求出 1 ! , 2 ! , . . . , n ! m o d    p 的结果 2. 用拓展那欧几里得算法 / 快速幂求出 n ! 的逆元 3. 根据 1 ( k − 1 ) ! = k k ! , 倒推出 ( n − 1 ) ! , ( n − 2 ) ! , . . . , 1 ! 的逆元 4. 根据 1 k = ( k − 1 ) ! k ! ,求出 1 到 n 的逆元 1.用循环求出1!,2!,...,n!\mod p的结果\\ 2.用拓展那欧几里得算法/快速幂求出n!的逆元\\ 3.根据\frac{1}{(k-1)!}=\frac{k}{k!},倒推出(n-1)!,(n-2)!,...,1!的逆元\\ 4.根据\frac{1}{k}=\frac{(k-1)!}{k!},求出1到n的逆元\\ 1.用循环求出1!,2!,...,n!modp的结果2.用拓展那欧几里得算法/快速幂求出n!的逆元3.根据(k1)!1=k!k,倒推出(n1)!,(n2)!,...,1!的逆元4.根据k1=k!(k1)!,求出1n的逆元
时间复杂度为O(n+log n)

#include <bits/stdc++.h>
using namespace std;
int n,p;
long long inv[3000010],fac[3000010];
long long pow(long long x,int y,int p){
    long long ans=1;
    for(;y;y>>=1){
        if(y&1)	ans=ans*x%p;
        x=x*x%p;
    }
    return ans;
}
int main()
{
	scanf("%d%d",&n,&p);
    fac[0]=1;
    for(int i=1;i<=n;i++)
        fac[i]=fac[i-1]*i%p;
    //求出1!,2!,...,n!
    inv[n]=pow(fac[n],p-2,p);
    //求出(n!)^(-1)
    for(int i=n-1;~i;i--){
        inv[i]=inv[i+1]*(i+1)%p;
    }
    //求出((n-1)!^(-1),(n-2)!^(-1),...,1!^(-1))
    for(int i=1;i<=n;i++)
        printf("%lld\n",fac[i-1]*inv[i]%p);
    //求出1^(-1),2^(-1),...,n^(-1)
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

钰见梵星

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值