跳到主要内容

乘法逆元-线性算法

题目

https://www.luogu.com.cn/problem/P3811 给定 n,pn,p1n1\sim n 中所有整数在模 pp 意义下的乘法逆元。 这里 aapp 的乘法逆元定义为 ax1(modp)ax\equiv1\pmod p 的解。

思路

  1. 费马小定理:逆元为x=ap2modpx=a^{p-2}\bmod p
  2. 扩展欧几里得算法:逆元为xx
  3. 线性算法

首先有111(modp)1^{-1}\equiv1(\bmod p),设p=ki+r,(1<r<i<p)p=k*i+r,(1<r<i<p),kk是商,rr是余数(r=pmodi)(r=p\bmod i),则ki+r0(modp)k*i+r\equiv0(\bmod p)两边同时乘上i1,r1i^{-1},r^{-1}得: kr1+i10(bmodp)k*r^{-1}+i^{-1}\equiv0(bmod p),移项得i1kr1(modp)i^{-1}\equiv -k*r^{-1} (\bmod p) 因此i1pi(pmodi)1(modp)i^{-1}\equiv -\lfloor{\frac{p}{i}}\rfloor*(p\bmod i)^{-1} (\bmod p) 注意要开LL

代码

/**
⠀⠀⠀⠀⠰⢷⢿⠄
⠀⠀⠀⠀⠀⣼⣷⣄
⠀⠀⣤⣿⣇⣿⣿⣧⣿⡄
⢴⠾⠋⠀⠀⠻⣿⣷⣿⣿⡀
0 ⠀⢀⣿⣿⡿⢿⠈⣿
⠀⠀⠀⢠⣿⡿⠁⠀⡊⠀⠙
⠀⠀⠀⢿⣿⠀⠀⠹⣿
⠀⠀⠀⠀⠹⣷⡀⠀⣿⡄
⠀⠀⠀⠀⣀⣼⣿⠀⢈⣧
*/

#include <bits/stdc++.h>

using namespace std;

#define endl '\n'
#define debug(x) cout<<"a["<<x<<"]="<<a[x]<<endl;
#define pr(x) cout<<x<<endl;
#define ct(x) cout<<x<<" ";
#define IOS ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)

typedef long long LL;
typedef pair<int, int> PII;
const int INF = 0x3f3f3f3f;
const int N = 3e6 + 10;

int n,p;
LL nvi[N];

int main() {
IOS;
#ifndef ONLINE_JUDGE
freopen("/Users/houyunfei/CLionProjects/MyCppWorkSpace/test.in", "r", stdin);
freopen("/Users/houyunfei/CLionProjects/MyCppWorkSpace/test.out", "w", stdout);
#endif
cin>>n>>p;
nvi[1]=1;
pr(1)
for(int i=2;i<=n;i++){
nvi[i]=(p-p/i)*nvi[p%i]%p;
pr(nvi[i])
}

return 0;
}