## 逆元简介

如果一个线性同余方程 $ax \equiv 1 \pmod b$，则 $x$ 称为 $a \mod b$ 的逆元，记作 $a^{-1}$。

## 如何求逆元

### 扩展欧几里得法：

```cpp
void ex_gcd(int a,int b,int&x,int&y)
{
	if(b==0)
	{
		x=1,y=0;
  		return;
 	}
 	ex_gcd(b,a%b,x,y);
 	int t=x;
 	x=y;
 	y=t-a/b*y;
 	return;
}
```

扩展欧几里得法和求解 [线性同余方程](/math/linear-equation/) 是一个原理，在这里不展开解释。

### 快速幂法：

这个要运用 [费马小定理](https://oi-wiki.org/math/fermat/)：

> 若 $p$ 为质数，$a$ 为正整数，且 $a$、$p$ 互质，则 $a^{p-1} \equiv 1 \pmod p$。

因为 $ax \equiv 1 \pmod b$；

所以 $ax \equiv a^{b-1} \pmod b$（根据费马小定理）；

所以 $x \equiv a^{b-2} \pmod b$；

然后我们就可以用快速幂来求了。

代码：

```cpp
#define ll long long
inline ll poW(ll a,ll b){
    long long ans=1;
    a%=p;
    while (b){
        if (b&1) ans=((ans*a)%p+p)%p;
        a=(a*a)%p; b>>=1;
    }
    return ans%p;
}
```

### 线性求逆元

但是如果要求的很多，以上两种方法就显得慢了，很有可能超时，所以下面来讲一下如何线性求逆元。

首先，很显然的 $1^{-1} \equiv 1 \pmod p$；

然后，设 $p=ki+j,j<i,1<i<p$，再放到 $\mod p$ 意义下就会得到：$ki+j \equiv 0 \pmod p$；

两边同时乘 $i^{-1},j^{-1}$：

$kj^{-1}+i^{-1} \equiv 0 \pmod p$；

$i^{-1} \equiv -kj^{-1}+ \pmod p$；

$i^{-1} \equiv -(\frac{p}{i}) (p \mod i)^{-1}$；

然后我们就可以推出逆元了，代码只有一行：

```cpp
a[i]=-(p/i)*a[p%i];
```

但是，有些情况下要避免出现负数，所以我们要改改代码，让它只求正整数：

```cpp
a[i]=(p-p/i)*a[p%i]%p;
```

这就是线性求逆元

## 逆元练习题

[【模板】乘法逆元](https://www.luogu.org/problemnew/show/P3811)

[同余方程](https://www.luogu.org/problemnew/show/P1082)

[\[AHOI2005\] 洗牌](https://www.lydsy.com/JudgeOnline/problem.php?id=1965)

[\[SDOI2016\] 排列计数](https://www.luogu.org/problemnew/show/P4071)
