洛谷 P3811【模板】乘法逆元

题目链接:https://www.luogu.com.cn/problem/P3811


1.什么是乘法逆元?

若a*x≡1(mod p)

则称x为a对p的逆元,记为inv[x]=a

逆元一般用来求形如(a/b)%p的式子的值

(详见这位大佬的博客


2.逆元怎么求?

exgcd

还记得这个式子吗?a*x≡1(mod p)

这个式子可以转化为a*x+p*y=1

这个时候就可以用exgcd来求逆元

BUT,对于这道题来说,exgcd的O(n log n)的时间复杂度会TLE,只能拿80分,最后一个点T掉了(但是对于普通的题来说这个方法还挺好用的)

80分的code:

#include<bits/stdc++.h>
using namespace std;
void exgcd(int &x,int &y,int a,int b)
{
    if(!b)
    {
        x=1;
        y=0;
        return;
    }
    exgcd(x,y,b,a%b);
    int t=x;
    x=y;
    y=t-a/b*y;
}
int main()
{
    int n,p;
    scanf("%d %d",&n,&p);
    for(int i=1;i<=n;i++)
    {
        int x=0,y=0;
        exgcd(x,y,i,p);
        printf("%d\n",(x%p+p)%p);
    }
    return 0;
}

费马小定理

费马小定理:若p为素数,a为正整数,且a、p互质。 则有:\[ a^{p-1} \equiv 1 (\bmod {p}) \]

这个我们就可以发现它这个式子右边刚好为 1 。

所以我们就可以放入原式,就可以得到:

a^(p-1) ≡1 (mod p)

两边同除以a

a^(p-2) ≡1/a (mod p)

什么?这可是数论,还敢写1/a

应该写a^(p-2) ≡ inv(a) (mod p)

但是,仍然会TLE......

于是代码略......

P.S:感谢这两位大佬的blog:

https://www.luogu.com.cn/blog/zjp-shadow/cheng-fa-ni-yuan)[https://www.luogu.com.cn/blog/zjp-shadow/cheng-fa-ni-yuan

https://blog.csdn.net/yu121380/article/details/81188274


逆元的线性递推式

经过一番神奇的操作,别问我怎么搞的,我也不会,得到了下面的式子:

inv[i]=(p-p/i)*inv[p%i]%p;

于是,就有了这个AC代码(源自https://www.cnblogs.com/song-/p/9724555.html):

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define ll long long
#define N 10101010
using namespace std;
int n,p;
ll inv[N];
int main()
{
    scanf("%d%d",&n,&p);
    inv[1]=1;
    printf("1\n");
    for(int i=2;i<=n;i++){
        inv[i]=(p-p/i)*inv[p%i]%p;
        printf("%lld\n",inv[i]);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/juruo-zzt/p/12045915.html