洛谷 P3811 【模板】乘法逆元

给定 n,pn,p ,求 1n1\sim n 中所有整数在 modp\bmod p 意义下的乘法逆元。

首先是乘法逆元的定义:

ax1modpax\equiv 1\bmod p,则 xxamodpa\bmod p 的逆元,记为 a1a^{-1}

线性求逆元:

modp\bmod p 意义下

pmoda=(papa)modpapamodp=(ppmoda)modpapamodp=(pmoda)modpamodp=(pmoda)pa1modpa1modp=(pmoda)1pamodpa1modp=(ppa)(pmoda)1modp \begin{aligned} p \bmod a&=(p-a\lfloor\frac{p}{a}\rfloor)\bmod p\\ a\lfloor\frac{p}{a}\rfloor\bmod p&=(p-p\bmod a)\bmod p\\ a\lfloor\frac{p}{a}\rfloor\bmod p&=-(p\bmod a)\bmod p\\ a\bmod p&=-(p\bmod a)\lfloor\frac{p}{a}\rfloor^{-1}\bmod p\\ a^{-1}\bmod p&=-(p\bmod a)^{-1}\lfloor\frac{p}{a}\rfloor\bmod p\\ a^{-1}\bmod p&=(p-\lfloor\frac{p}{a}\rfloor)(p\bmod a)^{-1}\bmod p\\ \end{aligned}

最后一步是为了防止出现负数,中间的一些步骤基本上是各种交换位置,其中的一些步骤是因为 modp\bmod p,可以去掉前面的 pp

#include<iostream>
#include<cstdio>
#define MAXN 3000010
using namespace std;
typedef long long ll;
int inv[MAXN],n,p;
int main(){
#ifdef WINE
    freopen("data.in","r",stdin);
#endif
    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; // long long 要加,因为此处乘法有可能溢出
        printf("%d\n",inv[i]);
    }
    return 0;
}

posted @ 2020-06-27 10:45  winechord  阅读(95)  评论(0编辑  收藏  举报