線性求逆元
阿新 • • 發佈:2021-07-24
線性求逆元
演算法功能
在 \(O(n)\) 的時間內求出某一序列各個數的逆元
演算法流程
- 首先, 預處理出序列
a[i]
的字首積s[i]
- 然後通過快速冪單點求出
s[n]
的逆元 - 倒序迴圈, 通過倒序乘原序列中的數, 求得
s[i]
的逆元 - 最後我們所需要的單點逆元, 就是
s[i]
的逆元與s[i-1]
的積
程式碼
/************************************************************************* > File Name: p5431.cpp > Author: Typedef > Mail: [email protected] > 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; }