题目大意:
题目链接:https://www.luogu.org/problem/P5431
给定
n
n
n个正整数
a
i
a_i
ai以及
k
,
p
k,p
k,p,定义它们在模
p
p
p意义下的乘法逆元为
1
a
i
\frac{1}{a_i}
ai1。
求
∑
i
=
1
n
k
i
a
i
\sum^{n}_{i=1}\frac{k^i}{a_i}
∑i=1naiki。
思路:
这道题要在近
O
(
n
)
O(n)
O(n)的复杂度内求出
n
n
n个数字的逆元。那么我们来看一下逆元的定义。
若
a
b
≡
1
(
m
o
d
p
)
ab\equiv 1(mod\ p)
ab≡1(mod p),则称
a
a
a为
b
b
b在模
p
p
p意义下的逆元。
也就是说,在模
p
p
p意义下,
a
a
a的逆元即为
1
a
\frac{1}{a}
a1。
那么我们设
s
[
i
]
=
Π
j
=
1
i
a
[
j
]
s[i]=\Pi^{i}_{j=1}a[j]
s[i]=Πj=1ia[j],然后设
i
n
v
=
1
s
[
n
]
inv=\frac{1}{s[n]}
inv=s[n]1,那么假设我们已经知道了
Π
j
=
1
i
a
[
j
]
\Pi^{i}_{j=1}a[j]
Πj=1ia[j]的逆元
i
n
v
i
inv_i
invi,那么显然有
1
a
i
−
1
=
i
n
v
i
×
s
i
−
1
\frac{1}{a_{i-1}}=inv_i\times s_{i-1}
ai−11=invi×si−1
因为
i
n
v
i
=
1
a
1
×
a
2
×
.
.
.
×
a
n
inv_i=\frac{1}{a_1\times a_2\times ...\times a_n}
invi=a1×a2×...×an1。
所以这样我们就可以在
O
(
n
)
O(n)
O(n)复杂度内求出所有数字的逆元。
然后
k
i
k^i
ki肯定是预处理的。这道题就解了。
代码:
#include <cstdio>
#include <string>
using namespace std;
typedef long long ll;
const int N=5000010;
ll p,k,a[N],s[N],num[N];
int n;
ll read()
{
ll d=0;
char ch=getchar();
while (!isdigit(ch)) ch=getchar();
while (isdigit(ch))
d=(d<<3)+(d<<1)+ch-48,ch=getchar();
return d;
}
ll power(ll x,ll m)
{
ll ans=1;
for (;m;m>>=1,x=x*x%p)
if (m&1) ans=ans*x%p;
return ans;
}
int main()
{
n=read(); p=read(); k=read();
num[0]=1;
s[0]=1;
for (int i=1;i<=n;i++)
{
num[i]=num[i-1]*k%p;
a[i]=read();
s[i]=s[i-1]*a[i]%p;
}
s[n]=power(s[n],p-2);
ll ans=0;
for (int i=n;i>=1;i--)
{
ans=(ans+s[i]*s[i-1]%p*num[i])%p;
s[i-1]=s[i]*a[i]%p;
}
printf("%lld",ans);
return 0;
}