exgcd

扩展欧几里得算法 (exgcd)

求整数 x,yx, y 使得 ax+by=gcd⁡(a,b)ax + by = \gcd(a, b)。

已知 bx′+(a mod b)y′=gcd⁡(b,a mod b)bx' + (a \bmod b)y' = \gcd(b, a\bmod b),而 a mod b=a−⌊a/b⌋ba \bmod b = a - \lfloor a/b \rfloor b,代入得:

bx′+(a−⌊a/b⌋b)y′=ay′+b(x′−⌊a/b⌋y′)bx' + (a - \lfloor a/b \rfloor b)y' = a y' + b(x' - \lfloor a/b \rfloor y')

因此原方程的解为:

x=y′,y=x′−⌊a/b⌋y′x = y', \quad y = x' - \lfloor a/b \rfloor y'

边界:当 b=0b=0 时,gcd⁡(a,0)=a\gcd(a,0)=a,取 x=1,y=0x=1, y=0。


流程:

  • 若 b=0b=0,返回 (x=1,y=0)(x=1, y=0)。
  • 否则递归求解 bx′+(a mod b)y′=gcd⁡(b,a mod b)bx' + (a\bmod b)y' = \gcd(b, a\bmod b)。
  • 根据递推式更新 x=y′, y=x′−⌊a/b⌋y′x = y',\ y = x' - \lfloor a/b \rfloor y'。

得到一组整数解(可能为负)。

C++
void exgcd(int a,int b,int &x,int &y){
	if(!b){
		x=1,y=0;
		return;
	}
	exgcd(b,a%b,x,y);
	int t=x;
	x=y;
	y=t-a/b*y;
}

可以用来求逆元(ax≡1(modm)ax\equiv 1\pmod m → ax+my=1ax+my=1,取 x mod mx \bmod m)、解线性同余方程。

中国剩余定理

P1495 【模板】中国剩余定理(CRT)/ 曹冲养猪

P1495 【模板】中国剩余定理(CRT)/ 曹冲养猪。

模数两两互质。

{x≡a1(modm1)x≡a2(modm2)⋮x≡an(modmn)\begin{cases} x \equiv a_1 \pmod{m_1} \\ x \equiv a_2 \pmod{m_2} \\ \quad \vdots \\ x \equiv a_n \pmod{m_n} \end{cases}

设 M=m1m2⋯mnM=m_1m_2\cdots m_n,Mi=MmiM_i=\frac{M}{m_i},ti=Mi−1t_i=M_i^{-1}。

我们构造:

x=∑i=1naiMitix=\sum_{i=1}^n a_iM_it_i

充分性

我们发现对于每一个 ii,只有在对应的那一位 aiMitimod  mia_iM_it_i\mod m_i 才不为 00,而且在 ii 的时候答案为 aia_i。

唯一性

我们需要证明 MM 以内没有其他解。

反证法,设 yy 也是一个解。

一定有:

x−y≡0(modai)M∣(x−y)x-y≡0\pmod {a_i}\\ M|(x-y)

所以 MM 以内只有一个解。

P4777 【模板】扩展中国剩余定理(EXCRT)

P4777 【模板】扩展中国剩余定理(EXCRT)。

我们发现 aa 不再互质了,于是需要换一种思路。我们考虑两两合并。

{x≡r1(modm1)x≡r2(modm2)\begin{cases} x \equiv r_1 \pmod{m_1} \\ x \equiv r_2 \pmod{m_2} \end{cases} x=k1m1+r1=k2m2+r2k1m1−k2m2=r2−r1x = k_1 m_1 + r_1 = k_2 m_2 + r_2\\ k_1m_1-k_2m_2=r_2-r_1

我们发现这个可以用 exgcd 求出来。

有解条件:d=gcd⁡(m1,m2)d=\gcd(m_1,m_2):

k1p1−k2p2=r2−r1dk_1p_1-k_2p_2=\frac{r_2-r_1}{d}

需要 d∣(r2−r1)d|(r_2-r_1)。


用 exgcd 求:

λ1p1+λ2p2=1\lambda_1 p_1 + \lambda_2 p_2 = 1 k1=r2−r1d⋅λ1,k2=−r2−r1d⋅λ2k_1 = \frac{r_2 - r_1}{d} \cdot \lambda_1,\quad k_2 = -\frac{r_2 - r_1}{d} \cdot \lambda_2 x∗=r1+k1m1=r1+r2−r1dλ1m1(modlcm(m1,m2))x^* = r_1 + k_1 m_1 = r_1 + \frac{r_2 - r_1}{d} \lambda_1 m_1\pmod {lcm(m_1,m_2)}

错排问题

错排问题 di=(i−1)∗(di−1+di−2)d_i=(i-1)*(d_{i-1}+d_{i-2})。