同余(exGCD CRT exCRT BSGS 等)
同余
同余
定义
给定正整数 \(m\),若 \(m\mid(a-b)\),即 \(m\bmod a=m\bmod b\),则称 \(a\) 与 \(b\) 模 \(m\) 同余,记作
其中 \(a\) 可表示为 \(a=b+mk\),\(k\in\mathbb{N}\),这是同余式子变形的重要形式。
性质
若 \(a\equiv b\pmod m\),\(c\equiv d\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}\),原方程的通解为:
一次同余方程
求解方程 \(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\) 的意义下唯一。
性质
即:
求法
设 \(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)
考虑求解同余方程组:
其中 \(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\) 的意义下有逆元。
构造:
因为 \(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}\) 即可,所以:
exCRT
还是上述问题,但当 \(m_i\) 不两两互质时,\(r_i^{-1}\) 不一定存在,此时考虑扩展中国剩余定理(exCRT)。
先考虑合并两个同余方程组成的方程组:
变形方程 \(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\)。
所以合并后的方程为:
可以推广到 \(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;
}
细节
- 计算过程总可能会超出 long long 存储空间,可使用 __int128 或龟速乘。
- 计算 \(k\) 的特解可以对 \(\frac{m_i}{g}\) 取模,因为 \(k=k^\prime+\frac{m_i}{g}\times t\),所以相邻大小的 \(k\) 之间的差值为 \(\frac{m_i}{g}\),取模可以减小数据规模。
题目
离散对数与 BSGS
给定 \(a,b,m\),求解方程 \(a^x\equiv b\pmod m\),\(x\) 被称为离散对数。
BSGS(大步小步)
设 \(t=\lceil\sqrt m\rceil\),\(x=it-j\),原方程等价于:
若 \(a_j\) 关于 \(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;
}

浙公网安备 33010602011771号