传送门
解题思路
在 (O(n)) 内求出 (n) 个数的逆元:
令 (S=sum_{i=1}^{n}a[i]),
则 (a[i]^{-1}=frac{S/a[i]}{S}=S_1[i-1]*S_2[n-i]*S^{-1})。
其中 (S_1) 为 (a[i]) 的前缀积,(S_2) 为 (a[i]) 的后缀积。
(O(n)) 预处理,(O(1)) 求。
因为这次要卡常,所以用了题解的快读(真的强大)
AC代码
#include<cstdio>
#include<iostream>
#include<cstring>
#include<iomanip>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn=5e6+5;
int n,p,k,k0,s1[maxn],s2[maxn],a[maxn];
long long ans;
template <typename T>
inline void read(T &x)//快读
{
char c;
x=0;
int fu=1;
c=getchar();
while(c>57||c<48){
if(c==45){
fu=-1;
}
c=getchar();
}
while(c<=57&&c>=48)
{
x=(x<<3)+(x<<1)+c-48;
c=getchar();
}
x*=fu;
}
int ksm(int a,int b){
if(b==1) return a%p;
long long res=ksm(a,b/2);
if(b&1) return (long long)res*res%p*a%p;
return (long long)res*res%p;
}
int main(){
read(n);
read(p);
read(k0);
k=k0;
s1[0]=s2[0]=1;
for(int i=1;i<=n;i++){
read(a[i]);
s1[i]=(long long)s1[i-1]*a[i]%p;
}
for(int i=1;i<=n;i++){
s2[i]=(long long)s2[i-1]*a[n-i+1]%p;
}
for(int i=1;i<=n;i++){
ans+=(long long)k*s1[i-1]%p*s2[n-i]%p;
k=(long long)k*k0%p;
}
printf("%lld",ans%p*ksm(s1[n],p-2)%p);
return 0;
}