题目
思路
前缀积线性求逆元即可。
设要求
a
1
,
a
2
,
a
3
,
…
,
a
n
a_1,a_2,a_3,…,a_n
a1,a2,a3,…,an的逆元。
那么设
s
i
=
s
i
−
1
∗
a
i
s_i=s_{i-1}*a_i
si=si−1∗ai,我们求
s
n
s_n
sn的逆元,则
1
s
i
1\over{s_i}
si1可线性递推,进一步可得出
1
a
i
1\over{a_i}
ai1
code:
#include<iostream>
#include<algorithm>
#include<string>
#include<cmath>
#include<cstdio>
using namespace std;
long long n,p,k,a[5000006][3],o,s;
inline long long read()
{
long long ans=0;
char u=getchar();
while (u>'9'||u<'0') u=getchar();
while (u<='9'&&u>='0') ans=ans*10+u-'0',u=getchar();
return ans;
}
pair<long long,long long> exgcd(long long a,long long b)
{
if (b==0) return pair<long long,long long> (1,0);
pair<long long,long long> tmp=exgcd(b,a%b);
return pair<long long,long long> (tmp.second,tmp.first-a/b*tmp.second);
}
long long ff(long long x)
{
pair<long long,long long> tmp=exgcd(x,p);
return (tmp.first%p+p)%p;
}
int main()
{
n=read(),p=read(),k=read();
o=k;
a[0][1]=a[0][2]=a[n+1][1]=a[n+1][2]=1;
for (long long i=1;i<=n;i++)
{
a[i][0]=read();
a[i][1]=a[i-1][1]*a[i][0]%p;
}
for (long long i=n;i>=1;i--) a[i][2]=a[i][0]*a[i+1][2]%p;
for (long long i=1;i<=n;i++)
{
s=(s+o*a[i-1][1]%p*a[i+1][2]%p)%p;
o=o*k%p;
}
printf("%lld",s*ff(a[1][2])%p);
return 0;
}