参考博客:传送门1
小记
1.本文重点是在于线性求逆元👨👧
2.对于求逆元,优先用扩展欧几里得,因为只要求互质,不要求是质数。
3.对于有取模的,一定要做好防爆保护(ll)
题目描述
给定n,p,求 1 ∼ n 1∼n 1∼n 中所有整数在模 p 意义下的乘法逆元。
基础知识
1.逆元是什么
若 a ∗ x ≡ 1 ( m o d b ) a*x\equiv1 (mod\,b) a∗x≡1(modb),且a与b互质,
那么x就是a在b模意义下的倒数,称x为a的逆元,记为 a − 1 a^{-1} a−1
2.扩展欧几里得exgcd(a,b,x,y)
可以求出 a*x+b*y=gcd(a,b)的整数解。
是gcd的扩展,故而使用时没有条件。
3.费马小定理
若 a是正整数,b是质数,且a与b互质,那么 a b − 1 ≡ 1 ( m o d b ) a^{b-1}\equiv1 (mod\, b) ab−1≡1(modb)。
因此 a ∗ a b − 2 ≡ 1 ( m o b b ) a* a^{b-2} \equiv1(mob\,b) a∗ab−2≡1(mobb), 即 a的逆元是 a b − 2 a^{b-2} ab−2
求逆元解法
<一>用扩展欧几里德
那么就是给 ( i ∗ x i ) % p = 1 (i*x_i)\%p=1 (i∗xi)%p=1找 x i x_i xi,
简化一下,就是 i*x=p*y+1, 又可以转为 i*x+p*y=1,
如果i,p互质,那么就是 i*x+p*y=gcd(i,p).
而这一题,i<n<p,且p是质数,i和p互为质,故可用。
<二> 用费马小定理
题目满足(1)i和p互质; (2)p是质数。那逆元就是 i p − 2 i^{p-2} ip−2
<三> 线性求逆元
🌟既然题目可以用一个线性函数描述,那么就有线性关系,
设p=k*i+r
∴ \therefore ∴ (k*i+r) %p=0
∴ r % p = ( − k ∗ i ) % p \therefore r\%p=(-k * i)\%p ∴r%p=(−k∗i)%p
又 在左右同乘上 i − 1 ∗ r − 1 i^{-1}* r^{-1} i−1∗r−1
∴ i − 1 % p = − k ∗ r − 1 % p \therefore i^{-1}\%p=-k * r^{-1}\%p ∴i−1%p=−k∗r−1%p
∴ i − 1 = − [ p i ] ∗ [ p % i ] − 1 \therefore i^{-1}=-[\frac{p}{i}]* [p\%i]^{-1}%p ∴i−1=−[ip]∗[p%i]−1
#include "cstdio"
typedef long long ll;
const int maxn=3e6+10;
int n,p,inv[maxn];
void solve()
{
inv[1]=1;
printf("%d\n",1);
for(int i=2;i<=n;++i)
{
inv[i]=(((ll)(-p/i)*inv[p%i])%p+p)%p;
//(ll)对于要取模的,防爆装置要做好
printf("%d\n",inv[i]);
}
}
int main()
{
scanf("%d %d",&n,&p);
solve();
return 0;
}