文章目录
同余式
1. 算法分析
1.1 同余式常用定理
1.1.1 欧拉公式/费马小定理
欧拉公式:
若gcd(a, n) = 1, 则aφ(n) = 1 (mod n)
费马小定理
若p是质数,则ap = a(mod p) => ap-1 = 1(mod p)
欧拉公式/费马小定理常用来化简式子,通过aφ(n) = 1 (mod n)的关系,把式子的一部分转换为1
1.1.2 威尔逊公式
- p为素数 <=> (p - 1)! ≡ -1(mod p)
- p为素数 <=> (p - 1)! ≡ (p - 1) (mod p)
- p为素数 <=> p | ((p-1)! + 1)
因此,当发现算式有 (p-1)! 时,可以考虑威尔逊定理的使用
1.1.3 扩展欧几里得
对于方程:
特殊地,ax+by=1有解 <=> gcd(a, b)=1
输入a,b,使用扩展欧几里得算法可以求出ax + by = gcd(a, b)的一个解为(x0, y0),那么ax + by = gcd(a, b)的通解为:
\begin{cases}
x = x0+(b/gcd)*t \\
y = y0-(a/gcd)*t
\end{cases}
ax + by=m的通解为:
\begin{cases}
x = x0*m/gcd+(b/gcd)*t \\
y = y0*m/gcd-(a/gcd)*t \\
(这里的x0、y0是ax+by=gcd求出来的)
\end{cases}
ax+by=gcd(a, b)和ax+by=m的通解的周期都是b/gcd,不会变
对ax+by=m进行变形,ax ≡ m (mod b)
则x∈[0, b),解的数目为gcd(a, b)个,第一个解在[0, b/gcd),第二个解在[b/gcd, 2b/gcd),…
1.2 乘法逆元
-
扩展欧几里得
ax ≡ 1(mod p) <=> ax + py ≡ 1(mod p),因此可以使用扩展欧几里得求ax + py ≡ 1(mod p)解逆元,求出来的逆元就是x -
费马小定理
ap-1 ≡ 1(mod p) <=> a的逆元为ap-2(mod p),当且仅当p为素数情况 -
线性求逆元
首先有
1-1≡1(mod p)
设
p=k * i + r, r < i, 1 < i < p
两边同时mod p,有
k * i + r ≡0 (mod p)
两边同时乘上i-1 * r-1,得到
k* r-1+ i-1≡ 0(mod p)
移项
i-1≡-k * r-1 (mod p)
i-1≡-⌊P/i⌋ * (p mod i)-1 (mod p)
以inv(i)表示i在mod p下的逆元,则有递推公式:
inv[i]= -(p/i) * inv[p % i]
1.3 求解同余式
1.3.1 求解一次同余式
求解一次同余式 ax ≡ 1(mod p), 直接乘法逆元求解
1.3.2 求解高次同余式
求解高次同余式 ax ≡ 1(mod p), 使用baby Step,Giant Step算法求解
1.4 中国剩余定理
- 原始版中国剩余定理
假设整数m1,m2, … ,mn两两互质,则对任意的整数:a1,a2, … ,an,方程组 (S) 有解,并且通解可以用如下方式构造得到:
\begin{cases}
x ≡ a1 (mod m1) \\
x ≡ a2 (mod m2) \\
x ≡ a3 (mod m3) \\
x ≡ a4 (mod m4)
\end{cases}
有解的判定条件,并用构造法给出了在有解情况下解的具体形式。
中国剩余定理说明:假设整数m1,m2, … ,mn两两互质,则对任意的整数:a1,a2, … ,an,方程组 有解,并且通解可以用如下方式构造得到:
x = ∑ i = 1 n a i ∗ t i ∗ M i + k M x = \sum_{i=1}^n\ {ai * ti * Mi} + kM x=i=1∑n ai∗ti∗Mi+kM
在mod M的意义下:
x = ( ∑ i = 1 n a i ∗ t i ∗ M i ) m o d M x = (\sum_{i=1}^n\ {ai * ti * Mi} ) mod M x=(i=1∑n ai∗ti∗Mi)modM
- 拓展版中国剩余定理
普通的中国剩余定理要求所有的mi互素, 那么如果不互素呢,求解同余方程组方法如下:
①这种情况采用两两合并的思想,假设要合并如下两个方程:
x = a1 + m1x2
x = a2 + m2x2
那么得到: a1+ m1x1 = a2 + m2x2 => m1x1 + m2x2 = a2 - a1
②使用扩展欧几里得算法得到一个最小的x1,从而得出最小的x使他满足:
x = a1 + m1x1 = a2 + m2x2
这样得到的是x的一个特解x’,当然也是最小正整数解
③所以x的通解一定是x’加上lcm(m1,m2)*k,这样才能保证x模m1和m2的余数是a1和a2.由此,我们把这个x’当作新方程的余数,把lcm(m1, m2)当作新的方程的模数
合并完成:x ≡ x’ (mod lcm(m1, m2))
1.5 思维同余性质
- 同余的考题很多结合距离可以回头的概念,比如自西向东一旦到了尽头那么又是自西向东,这样会产生同余的情况
- 还有很多考察欧拉公式等
2.板子
2.1 同余式常用定理
扩展欧几里得算法
// 扩展欧几里得算法:ax+by=gcd(a, b),返回值为d=gcd(a, b)
int exgcd(int a, int b, int &x, int &y) {
if (!b) {
// b==0时,x=1, y=0
x = 1, y = 0;
return a;
}
int d = exgcd(b, a % b, y, x); // b != 0时,gcd(a, b) = gcd(b, a % b), x = x, y = y - a/b * x;
y -= a / b * x;
return d;
}
2.2 乘法逆元
- 扩展欧几里得求逆元
// 扩展欧几里得算法:ax+by=gcd(a, b),返回值为d=gcd(a, b)
LL exgcd(LL a, LL b, LL &x, LL &y) {
if (!b) {
// b==0时,x=1, y=0
x = 1, y = 0;
return a;
}
LL d = exgcd(b, a % b, y, x); // b != 0时,gcd(a, b) = gcd(b, a % b), x = x, y = y - a/b * x;
y -= a / b * x;
return d;
}
LL getInv(LL a, LL mod) {
//求a在mod下的逆元,不存在逆元返回-1
LL x, y;
LL d = exgcd(a, mod, x, y);
return d == 1 ? (x % mod + mod) % mod: -1;
}
- 费马小定理求逆元
LL qmi(LL a, LL k, LL p) {
LL res = 1 % p; // res记录答案, 模上p是为了防止k为0,p为1的特殊情况
while(k) {
// 只要还有剩下位数
if (k & 1) res = (LL)res * a % p; // 判断最后一位是否为1,如果为1就乘上a,模上p, 乘