引入

我们知道模运算是可以加减乘的。加法和乘法很简单,直接将取模后的结果进行原运算即可;减法稍微复杂一点,我们设 \(p\) 是模数(素数)。原本 \(a-b\) 是大数减小数,但取模后不一定是大数减小数,有可能出现小数减大数的情况。也就是说如果按照加法和乘法的方式直接进行运算的话可能会出现负数。但我们并不希望运算的结果出现负数,我们希望它是一个 \(0\)\(p-1\) 的数。所以我们只需要在减法之后加上 \(p\) 再取一次模就好了(所以如果写题的时候出现了莫名其妙的 WA 或者负数就要注意了 QAQ )。很好理解,因为 0 \(\le a \le p-1\) 并且 0 \(\le b \le p-1\),所以减法结果不会比 \(-p\) 还要小。
但是这种方式到除法时就出现了不小的问题,模运算是不可除的。那如果一道题目既有除法又要取模呢?
那么是时候请出今天的主角 —— 逆元了。

正文

知周所众,取模是不支持除法运算的,所以我们只能把它转换成别的运算。比如乘法。为什么是乘法?因为除以一个数就相当于乘以它的倒数,也就是 \(\frac{a}{b}\) 等价于 \(a \cdot b^{-1}\)\(b^{-1}\) 等于 \(\frac{1}{b}\) )。
现在我们要找到求一个数除以 \(a\) 再模 \(p\)(素数)的方法。
因为 \(a \cdot a^{-1} = 1\),所以自然而然得出柿子 \(a \cdot a^{-1} \equiv 1 \pmod p\)。所以我们的目的就变成了找到一个数 \(x\) 来代替 \(a^{-1}\),也就是 \(\frac{1}{a}\)。那么现在就有 \(a \cdot x \equiv 1 \pmod p\)
这该怎么解呢?于是我们引入费马小定理。

费马小定理:设 \(p\) 是素数。对于任意整数 \(a\)\(p \nmid a\) ,都成立 \(a^{p-1} \equiv 1 \bmod p\).

证明略,可以看 OI Wiki 上的。
有没有觉得费马小定理的这个柿子很眼熟?如果没有也没关系,我们来给这个柿子进行进一步变形。将柿子中 \(a^{p-1}\) 拆一个 \(a\) 出来,就变成了 \(a \cdot a^{p-2}\)。由于这两个完全等价,所以费马小定理还是成立的。带回去就得到 \(a \cdot a^{p-1} \equiv 1 \pmod p\)
现在神奇的事情发生了。\(a^{p-2}\) 就是 \(a\) 在模 \(p\) 意义下的逆元。为什么?我们把两个柿子对比看看:一个是 \(a \cdot x \equiv 1 \pmod p\),一个是 \(a \cdot a^{p-1} \equiv 1 \pmod p\)。只有中间的部分不一样。
求完了。

Code

#include<bits/stdc++.h>
using namespace std;
long long ksm(long long a,long long k,long long p){ //一只快速幂。 
	long long ans=1;
	for(long long i=a;k!=0;k/=2,i=i*1ll*i%p) //求 a 的 p-2 次方。
		if(k%2!=0) ans=ans*1ll*i%p;
	return ans;
}
int main(){
	long long a,p;
	scanf("%lld%lld",&a,&p);
	printf("%lld\n",ksm(a,p-2,p));
	return 0;
}

不会快速幂的戳 这里

\(\sim\) ❀完结撒花❀ \(\sim\)