逆元定义
一般用于求
a
b
m
o
d
(
p
)
\dfrac{a}{b}\space mod (p)
ba mod(p)
若
a
∗
x
≡
1
(
m
o
d
p
)
a*x ≡ 1 \;(mod \;p)
a∗x≡1(modp) ,且 a与 p互质,那么我们就能定义: x 为 a 的逆元,记为
a
−
1
a^{-1}
a−1 ,所以我们也可以称 x 为 a 的倒数(
m
o
d
p
mod \;p
modp 意义如下)。
所以对于
a
b
m
o
d
p
\frac{a}{b}\ \; mod\;p
ba modp
我们就可以求出 b 在
m
o
d
p
mod\; p
modp 意义下的逆元,然后乘上 a;再
m
o
d
p
mod \; p
modp,就是这个乘法逆元的值了。
用什么方法?显然是拓展欧拉定理!
关于线性同余方程
a
∗
x
≡
c
(
m
o
d
b
)
a*x \equiv c \pmod {b}
a∗x≡c(modb) 的c=1的情况。我们就可以转化为解
a
∗
x
+
b
∗
y
=
1
a*x + b*y = 1
a∗x+b∗y=1这个方程
优点是什么?就是当a和p互质时,p不是质数也可以使用
(什么?你不会拓展欧拉定理?费马小定理也可以!)
若p为素数,a为正整数,且a、p互质。 则有
a
p
−
1
≡
1
(
m
o
d
p
)
a^{p-1} \equiv 1 (\bmod {p})
ap−1≡1(modp)
这个我们就可以发现它这个式子右边刚好为 1。
所以我们就可以放入原式,就可以得到:
a
∗
x
≡
1
(
m
o
d
p
)
a∗x≡1(modp)
a∗x≡1(modp)
a
∗
x
≡
a
p
−
1
(
m
o
d
p
)
a*x\equiv a^{p-1} \pmod p
a∗x≡ap−1(modp)
x
≡
a
p
−
2
(
m
o
d
p
)
x \equiv a^{p-2} \pmod p
x≡ap−2(modp)
代码实现就是快速幂啦!
拓展欧拉定理
#include<bits/stdc++.h>
#define N 3000010
typedef long long ll;
using namespace std;
int inv[N],n,p;
inline int read(){
int f=1,x=0;char ch;
do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');
return f*x;
}
int main(){
n=read();p=read();inv[1]=1;puts("1");
for(int i=2;i<=n;i++){
inv[i]=(ll)(p-p/i)*inv[p%i]%p;
printf("%d\n",inv[i]);
}
}
费马小定理
ll fpm(ll x, ll power, ll mod) {
x %= mod;
ll ans = 1;
for (; power; power >>= 1, (x *= x) %= mod)
if(power & 1) (ans *= x) %= mod;
return ans;
}
int main() {
ll x = fpm(a, p - 2, p); //x为a在mod p意义下的逆元
}