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;
}

 

posted @ 2021-04-23 20:12  cono奇犽哒  阅读(111)  评论(0)    收藏  举报