「乘法逆元」学习笔记

概念

若关于整数 a,b 的线性同余方程 ax1(modb) 存在解,则将 x 称作 amodb 的乘法逆元(简称逆元),记作 a1(modb),在不会引起误解时常记作 a1


  • b|a(整除)时,不存在 a 的逆元 a1(modb)
  • 特别的,有111(modb)
    • 证明:对于整数 b,有 1×11(modb),故 1modb 的逆元为 1

性质

  • n 为正整数,则 a1n+1(mod2n+1)
    • 证明:已知 2x1(mod2n+1),设 2x=(2n+1)k+1,又因为 2x 为偶数,k 的最小整数解为 1,代入得 x=n+1
  • b 为质数,且 a<b,则 a1ab2(modb)
    • 证明:需要用到费马小定理,暂时不会,学了回来再写

求法

1. exgcd

详见 exgcd

例题:同余方程

  • 时间复杂度 O(logmax(a,b))

2.线性求 1n 或单个数的逆元(递推/递归)

限制条件:b 为质数


证明:

k=bir=bmodi,则有:

b=k×i+r0(modb)

两边同时乘上 i1×r1 得:

k×r1+i1(modb)

移项得 i1k×r1(modb)

k=bir=bmodi 代入得:

i1bi×(bmodi)1(modb)

考虑消除负数取模对答案的影响,故推出逆元:

i1={1i=1(bbi)×(bmodi)1i1

  • 递推求 1n 的逆元,O(n) 预处理,O(1) 查询
  • 递归求任意数的逆元,时间复杂度 O(n13)

例题

代码如下(递推):

#include<bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
template<typename Tp> inline void read(Tp&x)
{
x=0;register bool z=1;
register char c=getchar();
for(;c<'0'||c>'9';c=getchar()) if(c=='-') z=0;
for(;'0'<=c&&c<='9';c=getchar()) x=(x<<1)+(x<<3)+(c^48);
x=(z?x:~x+1);
}
void wt(int x){if(x>9)wt(x/10);putchar((x%10)+'0');}
void write(int x){if(x<0)putchar('-'),x=~x+1;wt(x);}
int n,p,inv[10000010];
void niyuan(int n)
{
inv[1]=1;
for(int i=2;i<=n;i++) inv[i]=((p-p/i)*inv[p%i])%p;
}
signed main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
read(n),read(p);
niyuan(n);
for(int i=1;i<=n;i++)
write(inv[i]),puts("");
}
posted @   卡布叻_周深  阅读(20)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
点击右上角即可分享
微信分享提示