乘法逆元
给定 \(n\) 个正整数 \(a_i\) ,求它们在模 \(p\) 意义下的乘法逆元。
由于输出太多不好,所以将会给定常数 \(k\),你要输出的答案为:
\[\sum\limits_{i=1}^n\frac{k^i}{a_i}
\]
答案对 \(p\) 取模。
逆元
已知求逆元的方法有快速幂\(a^{-1} = power(a,p - 2,p)\)
线性递推求逆元
inv[1] = 1;
for (int i = 2; i <= n; ++i) {
inv[i] = (long long)(p - p / i) * inv[p % i] % p;
}
经过观察发现本题数并不是连续的因此我们不能用这种方法
设\(S_n\)为\(a_n\)的前缀积\(( a_1 \times a_2 \times a_3 \dots a_n)\)
求得$S_n $的逆元称作 \(Sv_n\)
因为\(Sv_n\)为\(a_n\)的积逆元,由逆元互逆运算法则\(Sv_n \times a_n = Sv_{n-1}\)
\[a^{-1}_i = S_{i - 1} \times Sv_i
\]
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 5e6 + 10;
ll a[N];
ll s[N],sv[N];
ll n,p,k,ans;
ll read()
{
ll x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9')
{
if (ch == '-')
{
f = -1;
}
ch = getchar();
}
while (ch >= '0' && ch <= '9')
{
x = x * 10 + ch - '0';
ch = getchar()
;
}
return x * f;
}
ll power(int a,int b)
{
ll res = 1;
while(b)
{
if(b&1)res = (ll)res * a % p;
a = (ll)a * a % p;
b >>= 1;
}
return res;
}
int main()
{
n = read();
p = read();
k = read();
s[0] = 1;
for(int i = 1 ; i <= n ; i ++ )
{
a[i] = read();
s[i] = (a[i] * s[i - 1]) % p;
}
sv[n + 1] = power(s[n],p-2);
for(int i = n; i >= 1 ; i --)
{
sv[i] = (sv[i + 1] * a[i]) % p;
}
ll tmp = k;
for(int i = 1 ; i <= n ; i ++ )
{
ans =(ans + ((sv[i + 1] * s[i - 1]) % p ) * tmp) % p;
tmp = (tmp * k )% p;
}
cout << ans << "\n";
}
“风雪越是呼啸,雪莲越是绽放”