概述
本文會講解同餘與逆元的概念,並從 \(exgcd\) 開始擴充套件延伸。
\(\bold{exgcd}\) 的應用 - 一元的線性同餘方程
一元的線性同餘方程的基本形式為 \(ax \equiv b(\bmod m)\),\(\equiv\) 表示在模 \(m\) 意義下相等,即 \(ax \bmod m=b \bmod m\)。
顯然,若有 \(ax \equiv b(\bmod m)\),則存在 \(k \in \mathbb{Z}\) 滿足 \(ax+km=b\)。
其中 \(x\) 和 \(k\) 是未知數,於是這個方程可以用 \(exgcd\) 解,只不過我們只關注 \(x\) 的值罷了。
\(\bold{exgcd}\) 的應用 - 逆元
我們知道,模運算具有可加性和可乘性。
\(eg.\)
\(\because5\bmod 3=2,7\bmod3=1\)
\(\therefore 5\times7\bmod 3=(5\bmod 3)\times(7\bmod 3)\bmod3=2\times1\bmod3=2\)
但如果是除法呢?
\(eg.\)
\(\because12\bmod 10=2,6\bmod10=6\)
\(\therefore 12\div6\bmod 10=(12\bmod 10)\div(6\bmod 10)\bmod10=2\div6\bmod10=\text{ }?\)
這樣做顯然是不行的,於是我們引入逆元的概念。
我們知道,除以一個數相當於成上它的倒數,那我們也有模意義下的倒數。
\(eg.\text{ }3\times7\equiv1(\bmod10)\)
於是我們稱 \(7\) 是 \(3\) 在模 \(10\) 意義下的逆元,記作:\(7=\operatorname{inv}(3)\)。
或者記作:\(7=\frac{1}{3}(\bmod 10)\)。
第二種寫法未免看著有點奇怪,實際上,我們可以擴充出模意義有理數的概念:
\(\operatorname{inv}(a)\times b\equiv\frac{b}{a}(\bmod m)\)
當然 \(a\) 存在模 \(m\) 意義下的逆元的充要條件是 \(gcd(a,m)=1\),這點是顯然的。
大家可以看一下這道題:P2613 【模板】有理數取餘。
注意到 \(ax=1(\bmod m)\) 的解 \(x\) 即為 \(\operatorname{inv}(a)\),於是就轉換成一個一元的線性同餘方程,\(exgcd\) 求解即可。
線性求逆元
模板題:P3811 【模板】模意義下的乘法逆元
我們可以用線性遞推的方式 \(O(n)\) 求出 \(\operatorname{inv}([1,m])(\bmod m)\)。
初始化 \(\operatorname{inv}(1)=1\)。
當我們計算 \(\operatorname{inv}(a)\) 時:
令 \(k=\lfloor\frac{m}{a}\rfloor,d=m\bmod a\)
\(\therefore ak+d=m\)
\(\therefore ak+d\equiv0(\bmod m)\)
\(\therefore ak\equiv -d(\bmod m)\)
\(\therefore a\equiv -d\cdot\operatorname{inv}(k)(\bmod m)\)
\(\therefore \operatorname{inv}(a)\equiv-\operatorname{inv}(d)\cdot k(\bmod m)\)【兩邊同時取倒數,顯然 \(a\neq0\)】
\(\small{即}\):
於是我們就找到了線性遞推的式子。
#define Mod(a,m) ((a%m+m)%m)
void calc(){
inv[1]=1;
for(int i=2;i<=n;i++) inv[i]=Mod(-inv[m%i]*(m/i),m);
}
也可以打成記搜。
#define Mod(a,m) ((a%m+m)%m)
int inv(int a){
if(a==1) return 1;
if(ans[a]) return ans[a];
return Mod(-inv(m%a)*(m/a),m);
}