P5431 【模板】乘法逆元 2

Problem:

题目描述

给定 n 个正整数 ai ,求它们在模 p 意义下的乘法逆元。

由于输出太多不好,所以将会给定常数 k,你要输出的答案为:

i=1nkiai

答案对 p 取模。

输入格式

第一行三个正整数 n,p,k,意义如题目描述。
第二行 n 个正整数 ai,是你要求逆元的数。

输出格式

输出一行一个整数,表示答案。

样例 #1

样例输入 #1

6 233 42
1 4 2 8 5 7

样例输出 #1

91

提示

对于 30% 的数据,1n105

对于 100% 数据,1n5×1062k<p1091ai<p,保证 p 为质数。

Solution

注意到此题的 n 高达 5e6,因此我们无法求 O(n) 次逆元。

因此考虑通分,因为通分后就只剩一个大分数了,那么只用求分母的一次逆元即可。

很显然通分后是 ikijiajai

下面分母求一次逆元即可,上面分子的话我们不难发现 jiaj=(j<iaj)(j>iaj),直接预处理前后缀积,然后 ki 递推维护即可。

时间复杂度 O(n)

代码
#include<bits/stdc++.h>
using namespace std;
#define inf 0x7fffffff
#define timeused() (double)clock()/CLOCKS_PER_SEC
#define rep(i,a,b) for(int i=a,i##end=b;i<=i##end;++i)
#define repp(i,a,b) for(int i=a,i##end=b;i>=i##end;--i)
#define mp make_pair
#define pb push_back
typedef long long ll;
typedef unsigned long long ull;
template<typename T> inline T rd(T& x){
    T f=1;x=0;char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    for(; isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+(T)(c-'0');
    x*=f;
    return x;
}
ll n,p,k,a[6000005],pre[6000005],suf[6000005],ans;
ll qp(ll b,ll P,ll mod){
    ll ans=1,base=b;
    while(P){
        if(P&1) ans=ans*base%mod;
        base=base*base%mod;
        P>>=1;
    }
    return ans;
}
int main(){
    rd(n);
    rd(p);
    rd(k);
    rep(i,1,n) rd(a[i]);
    pre[0]=1;
    suf[n+1]=1;
    rep(i,1,n) pre[i]=pre[i-1]*a[i]%p;
    repp(i,n,1) suf[i]=suf[i+1]*a[i]%p;
    ll base=1;
    rep(i,1,n){
        base=base*k%p;
        ans+=pre[i-1]*suf[i+1]%p*base%p;
        ans%=p;
    }
    printf("%lld",ans*qp(pre[n],p-2,p)%p);
}
posted @   lstqwq  阅读(84)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
点击右上角即可分享
微信分享提示
主题色彩