乘法逆元进阶运用
线性求逆元
令 。
有
在两边分别乘上 、。
得到
由于 故递推式成立。
乘法逆元的积性——离线逆元
我们说对于乘法逆元有:。
证明: ,。
将两式相乘,,显然 是 的逆元。
于是乘法逆元积性得证,我们可以用它解决一些问题。
例如
前缀积。设 表示从 到 的前缀积,那么要求 的区间积,需要 。可是有时候乘积太大需要取模,那么这时候的除法需要乘法逆元,但是 可能很大,逆元数组存不下(这里是线性逆元),这时候就要用到这条结论:前缀积的逆元,就是逆元的前缀积。
设 ,。
我们可以得到递推式:。
也可以求单个值 。
那么要线性求逆元,需要先求出 ,可以用费马小定理( 是质数)或Exgcd。
总时间复杂度 ,接近线性。
模板题:P5431【模板】乘法逆元 2
此题卡的很死,注意速度和运算空间
#include <bits/stdc++.h>
#define rei register int
#define ll long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define rep(i, s, n, c) for (register int i = s; i <= n; i+=c)
#define repd(i, s, n, c) for (register int i = s; i >= n; i-=c)
#define CHECK cout<<"WALKED"<<endl;
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0' && ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x*f;}
#define pb push_back
#define ls id<<1
#define rs id<<1|1
const int INF = INT_MAX;
long long binpow(long long a, long long b, ll mod){long long res = 1; while (b > 0){if (b & 1) res = res * a % mod;a = a * a % mod; b >>= 1; } return res;}
using namespace std;
int a[5000006], pre[5000006], inv_pre[5000006], inv[5000006];
int main()
{
int n; ll p, k;
scanf("%d%lld%lld", &n, &p, &k);
pre[0] = 1;
for (register int i = 1; i <= n; i++) {
a[i] = read();
pre[i] = 1ll * pre[i - 1] * a[i] % p;
}
inv_pre[n] = binpow(pre[n], p - 2, p);
for (int i = n; i > 0; i--) {
inv[i] = 1ll * pre[i - 1] * inv_pre[i] % p;
inv_pre[i - 1] = 1ll * inv_pre[i] * a[i] % p;
}
ll ans = 0;
for (int i = 1, t = k; i <= n; i++) {
ans = (1ll * inv[i] * t % p + ans) % p;
t = 1ll * t * k % p;
}
printf("%lld\n", ans);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现