JS1k: Breathing Galaxies (1013 bytes)

同余(exGCD CRT exCRT BSGS 等)

同余

同余

定义

给定正整数 \(m\),若 \(m\mid(a-b)\),即 \(m\bmod a=m\bmod b\),则称 \(a\)\(b\)\(m\) 同余,记作

\[a\equiv b\pmod m \]

其中 \(a\) 可表示为 \(a=b+mk\)\(k\in\mathbb{N}\),这是同余式子变形的重要形式。

性质

\(a\equiv b\pmod m\)\(c\equiv d\pmod m\),则:

\[a\pm c\equiv c\pm d\pmod m\\ ac\equiv bd\pmod m\]

且:

\[ak\equiv bk\pmod m \]

但注意若 \(ac\equiv bc\pmod m\) 不能得到 \(a\equiv b\pmod m\)。当且仅当 \(\gcd(c,m)=1\) 时可以得到,证明:

\(\gcd(c,m)=1\) 时,\(c\) 有逆元 \(c^{-1}\),即存在正整数 \(c^{-1}\) 使得 \(c\times c^{-1}\equiv 1\pmod m\)

所以 \(ac\times c^{-1}\equiv bc\times c^{-1}\pmod m\)\(a\equiv b\pmod m\),证毕。


exGCD

裴蜀定理

对任意不全为 0 的整数 \(a,b\),存在整数 \(x,y\),使得 \(ax+by=\gcd(a,b)\)

裴蜀定理说明所有形如 \(ax+by\) 的整数线性组合,最小的正值恰好是 \(\gcd(a,b)\)

扩展欧几里得算法

证明参考

实现

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

其中 \(a,b\) 为系数,\(x,y\) 是方程的一组特解,函数返回值为 \(\gcd(a,b)\)

通解

考虑整数方程 \(ax+by=c\),令 \(g=\gcd(a,b)\),先求出 \(ax_0+by_0=g\) 的一组特解 \(x_0,y_0\),再将方程左右两边同时乘 \(\frac{c}{g}\) 得到原方程的一组特解 \(x^\prime,y^\prime\),其中 \(x^\prime=x_0\times\frac{c}{g},y^\prime=y_0\times\frac{c}{g}\),原方程的通解为:

\[x=x^\prime+\frac{b}{g}\times t,y=y^\prime-\frac{b}{g}\times t,t\in\mathbb{Z} \]

一次同余方程

求解方程 \(ax\equiv b\pmod m\)

容易发现方程可转化为 \(ax+my=b\),用扩展欧几里得算法求解即可,另外,令 \(g=\gcd(a,m)\),若 \(g\nmid b\),则方程无解。因为 \(x=x^\prime+\frac{m}{g}\times t\),则在 \([0,m)\) 范围内,共有 \(g\) 组解。


乘法逆元

定义

\(ab\equiv 1\pmod m\),则称 \(b\)\(a\) 的乘法逆元,记作 \(a^{-1}\)

当且仅当 \(\gcd(a,m)=1\) 时,逆元存在,且在模 \(m\) 的意义下唯一。

性质

\[\frac{x}{a}\equiv x\times a^{-1}\pmod m \]

即:

\[\frac{x}{a}\bmod m=x\times a^{-1}\bmod m \]

求法

\(x\)\(a\)\(m\) 意义下的乘法逆元,因为 \(ax\equiv 1\pmod m\),则 \(ax+my=1\),因为 \(\gcd(a,m)=1\),则 exGCD 求解一次同余方程即可。

另解:

使用费马小定理也可求出,费马小定理:若 \(p\) 是质数且 \(p\nmid a\),则 \(a^{p-1}\equiv1\pmod m\),于是 \(a^{-1}\equiv a^{p-2}\pmod m\),快速幂即可求出 \(a^{-1}\)


中国剩余定理(CRT)

考虑求解同余方程组:

\[\begin{cases} x\equiv a_1\pmod {m_1}\\ x\equiv a_2\pmod {m_2}\\ \cdots\\ x\equiv a_k\pmod {m_k} \end{cases} \]

其中 \(m_i\) 两两互质。

设:

\[M=\prod_{i=1}^km_i,r_i=\frac{M}{m_i} \]

显然 \(\forall1\le i,j\le k\)\(i\ne j\),有 \(m_j\mid r_i\),又因为 \(m_i\) 两两互质,则 \(\gcd(m_i,r_i)=1\),所以 \(r_i\) 在模 \(m_i\) 的意义下有逆元。

构造:

\[y_i\equiv a_ir_i^{-1}\pmod {m_i} \]

因为 \(x_i\equiv a_i\pmod {m_i}\),则 \(x_ir_i^{-1}\equiv a_ir_i^{-1}\pmod m\),则 \(x_i=r_iy_i\)

构造 \(y_i=a_ir_i^{-1}\) 即可,所以:

\[x=\sum_{i=1}^kx_i=\sum_{i=1}^ka_ir_ir_i^{-1}\bmod M \]

exCRT

还是上述问题,但当 \(m_i\) 不两两互质时,\(r_i^{-1}\) 不一定存在,此时考虑扩展中国剩余定理(exCRT)。

先考虑合并两个同余方程组成的方程组:

\[\begin{cases} x\equiv a_1\pmod {m_1}\\ x\equiv a_2\pmod {m_2} \end{cases} \]

变形方程 \(1\),得到 \(x=a_1+m_1k\),代入方程 \(2\)\(a_1+m_1k\equiv a_2\pmod{m_2}\),转化为 \(m_1k\equiv a_2-a_1\pmod{m_2}\),此时转化为了一个一次同余方程,未知数为 \(k\)。(可以转化为 \(m_1k+m_2y=a_2-a_1\))容易解出 \(k\) 的一个特解 \(k^\prime\),设 \(g=\gcd(m_1,m_2)\)\(k\) 的通解为 \(k=k^\prime+\frac{m_2}{g}\times t\)

带回 \(x\) 得到 \(x=a_1+m_1k=a_1+m_1k^\prime+\frac{m_1m_2}{g}\times t=a_1+m_1k^\prime+\text{lcm}(m_1,m_2)\times t\)

所以合并后的方程为:

\[x\equiv a_1+m_1k^\prime\pmod m \]

可以推广到 \(k\) 个方程的方程组,一个一个合并即可。

实现

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

int ans = a[1], mod = m[1];
for (int i = 2, x, y; i <= n; ++i){
	int g = exgcd(mod, m[i], x, y);
	int k = (__int128)((a[i] - ans) / g) * x % (m[i] / g);
	if (k < 0){
		k += m[i] / g;
	}
	int MOD = (__int128)mod * m[i] / g;
	ans = (ans + (__int128)mod * k) % MOD;
	mod = MOD;
}

细节

  1. 计算过程总可能会超出 long long 存储空间,可使用 __int128 或龟速乘。
  2. 计算 \(k\) 的特解可以对 \(\frac{m_i}{g}\) 取模,因为 \(k=k^\prime+\frac{m_i}{g}\times t\),所以相邻大小的 \(k\) 之间的差值为 \(\frac{m_i}{g}\),取模可以减小数据规模。

题目

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


离散对数与 BSGS

给定 \(a,b,m\),求解方程 \(a^x\equiv b\pmod m\)\(x\) 被称为离散对数。

BSGS(大步小步)

\(t=\lceil\sqrt m\rceil\)\(x=it-j\),原方程等价于:

\[\frac{a^{it}}{a^j}\equiv b\pmod m \]

\(a_j\) 关于 \(m\) 有逆元,则进一步转化为:

\[a^{it}\equiv ba^j\pmod m \]

由此可见,BSGS 算法要求 \(a\) 在模 \(m\) 的意义下有逆元,即 \(\gcd(a,m)=1\)

接下来预处理右边的 \(ba^j\),存入哈希表,再枚举左边的 \(a^{it}\),查找是否有匹配的 \(ba^j\),匹配时返回 \(x=it-j\)

实现

int BSGS(int a, int b, const int mod){
	int B = sqrt(mod) + 1;
	unordered_map <int, int> mp;
	int at = 1, k = 1;
	mp[b] = 0;
	for (int i = 1; i <= B; ++i){
		mp[(b *= a) %= mod] = i;
		(at *= a) %= mod;
	}
	for (int i = 1; i <= B; ++i){
		if (mp.count((k *= at) %= mod)){
			return i * B - mp[k];
		}
	}
	return -1;
}

题目

P3846 【模板】BSGS / [TJOI2007] 可爱的质数

posted @ 2026-07-29 15:12  __int127  阅读(14)  评论(0)    收藏  举报