n项分数关于p的逆元和
题目描述:
给定 n 个正整数 ai ,求它们在模 p 意义下的乘法逆元。
由于输出太多不好,所以将会给定常数 k,你要输出的答案为:
n个分数,(k^i)/ai(1<=i<=n)关于p的逆元的和
思路:有大佬利用性质:n项有理数每一项的逆元a'=所有数乘积的逆元*除去当前数所有数乘积,这条性质,
用前缀积后缀积做,还有一个更简单得性质,就是逆元是可加的,即先把所有数的和求出来,再求该分数的逆元,
也就是所有分数的逆元的和。
AC代码:
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 10000005; const int inf = 0x3f3f3f3f; const int mod = 19260817; void read(ll& sum) { sum = 0; char p = getchar(); for (; !isdigit(p); p = getchar()); for (; isdigit(p); p = getchar()) { sum = sum * 10 % mod + p - '0'; } sum% mod; } void Exgcd(ll a, ll b, ll& x, ll& y) { if (b == 0) { x = 1, y = 0; return; } Exgcd(b, a % b, y, x), y -= a / b * x; } ll n, p, k; ll fpm(ll a, ll n, ll p) { ll ans = 1; while (n) { if (n & 1) { ans = (ans * a) % p; } n >>= 1; a = (a * a) % p; } return ans; } int main() { //freopen("test.txt", "r", stdin); scanf("%lld%lld%lld", &n, &p, &k); ll a=0,b=1,t,c; for (int i = 1,c=k%p; i <= n; i++,c=c*k%p) { scanf("%lld", &t); a = (a * t + b * c) % p; b = b * t % p;//通分求和 } ll x, y; Exgcd(b, p, x, y); printf("%lld",a*(x%p+p)%p);//扩展欧几里得或者费马小定理(p是质数) //printf("%lld\n", a * fpm(b, p - 2,p) % p); return 0; }