线性求逆元

线性求逆元

传送锚点

算法功能

\(O(n)\) 的时间内求出某一序列各个数的逆元

算法流程

  • 首先, 预处理出序列 a[i] 的前缀积 s[i]
  • 然后通过快速幂单点求出 s[n] 的逆元
  • 倒序循环, 通过倒序乘原序列中的数, 求得 s[i] 的逆元
  • 最后我们所需要的单点逆元, 就是 s[i] 的逆元与 s[i-1] 的积

代码

/*************************************************************************
    > File Name: p5431.cpp
    > Author: Typedef 
    > Mail: 1815979752@qq.com 
    > Created Time: 2021年07月09日 星期五 07时32分57秒
    > Tags: 
 ************************************************************************/
#include<bits/stdc++.h>
using namespace std;
const int N=5e6+7;
typedef long long ll;
ll n,p,k,K,ans=0;
ll a[N],inv[N];
ll s[N];
template<class T>void qread(T &x){
	x=0;bool f=0;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-') f=1;c=getchar();}
	while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^48);c=getchar();}
	if(f) x=-x;
}
ll qpow(ll a,ll b){
	ll res=1;
	while(b){
		if(b&1) res=(res*a)%p;
		a=(a*a)%p;
		b>>=1;
	}
	return res;
}
int main(){
	inv[n+1]=s[0]=1;
	qread(n),qread(p),qread(k);
	for(int i=1;i<=n;i++) qread(a[i]),s[i]=(s[i-1]*a[i])%p;
	inv[n+1]=qpow(s[n],p-2),K=k;
	for(int i=n;i;i--) inv[i]=(inv[i+1]*a[i])%p;
	for(int i=1;i<=n;i++){
		ans=(ans+(K*(inv[i+1]*s[i-1]%p)%p)%p)%p;
		K=(K*k)%p;
	}
	printf("%lld\n",ans);
	return 0;
}
posted @ 2021-07-24 08:06  actypedef  阅读(101)  评论(1编辑  收藏  举报