码迷,mamicode.com
首页 > 其他好文 > 详细

luogu P3811 【模板】乘法逆元

时间:2019-01-25 22:47:56      阅读:216      评论:0      收藏:0      [点我收藏+]

标签:快速幂   eset   线性   lis   技术分享   str   efi   math   gcd   

技术分享图片

技术分享图片

solution 1:

费马小定理

若p为素数,a为正整数,且a、p互质,则有a^(p - 1)≡ 1(mod p)

那么a的逆元就是a^(p - 2)

用一个快速幂即可

//t两个点

#include<cstdio>
using namespace std;
#define int long long

int p;

int quickpow(int n,int k) {
    int ans = 1;
    while(k) {
        if(k & 1)
            ans = ans * n % p;
        n = n * n % p;
        k >>= 1;
    }
    return ans % p;
}

 main() {
    int n;
    scanf("%lld%lld",&n,&p);
    for(int i = 1; i <= n; i++)
        printf("%lld\n",quickpow(i,p - 2));
    return 0;
}

solution 2:

exgcd

a * x = 1(mod p)

则 a * x + p * y = 1

//t一个点

#include<cstdio>
using namespace std;

int x,y;

void exgcd(int a,int b) {
    if(b == 0) {
        x = 1;
        y = 0;
        return ;
    }
    exgcd(b,a % b);
    int tmp = x;
    x = y;
    y = tmp - a / b * y;
}

int main() {
    int n,p;
    scanf("%d%d",&n,&p);
    for(int i = 1; i <= n; i++) {
        exgcd(i,p);
        printf("%d\n",(x % p + p)% p);
    }
    return 0;
}

solution 3:

线性递推

根据费马小定理的公式进行推导得出

#include<cstdio>
using namespace std;
#define maxn 3000010
#define ll long long

ll inv[maxn];

int main() {
    int n,p;
    scanf("%d%d",&n,&p);
    inv[1] = 1;
    printf("1\n");
    for(int i = 2; i <= n; i++) {
        inv[i] = (ll)(p - p / i) * inv[p % i] % p;
        printf("%lld\n",inv[i]);
    }
    return 0;
}

 

luogu P3811 【模板】乘法逆元

标签:快速幂   eset   线性   lis   技术分享   str   efi   math   gcd   

原文地址:https://www.cnblogs.com/sevenyuanluo/p/10307363.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!