1. 相关定理
-
费马小定理
若p是质数,则对于任意整数a,有ap≡a(modp) -
欧拉定理
若正整数a,n互质,则aϕ(n)≡1(modn),其中ϕn为欧拉函数 -
欧拉定理的推论
若正整数a,n互质,则对于任意正整数b,有ab≡abmodϕ(n)(modn)
取模下的计算技巧 【加、减、乘、乘方、除】
对于要求我们把答案对一个质数 p
取模后输出:
-
对于
a + b
,a - b
,a * b
这样的算式,可在计算前先把a
,b
对p
取模 -
对于乘方算式,根据欧拉定理的推论,可以先把
底数
对p
取模、指数
对 ϕ(p) 取模,再计算乘方。特别地,求乘方ab(modn) :对于当 a,n 不一定互质且 b > ϕ(n)时,有ab≡abmodϕ(n)+ϕ(n)(modn)
-
除法 -> 乘法逆元:bp−2 即为 b 的乘法逆元。
特别地,若只保证
b,m
互质,那么乘法逆元可以通过求解同余方程 b∗x≡1(modm) 得到。因此
a / b
,可以先将a,b
对p
取模,再计算 a∗b−1modp 为最终结果。
2. 拓展欧几里得算法
Bezout
定理
对于任意整数 a,b ,存在一对整数 x,y ,满足 ax+by=gcd(a,b)
#include <bits/stdc++.h>
using namespace std;
int exgcd(int a, int b, int &x, int &y) {
if(b == 0) { x = 1, y = 0; return a; }
int d = exgcd(b, a % b, x, y);
int z = x; x = y; y = z - y * (a / b);
return d;
}
int main() {
int a, b, x, y;
while(cin >> a >> b){
int d = exgcd(a, b, x, y);
cout << x << " " << y << " " << d << endl;
}
}
x, y
是以引用的方式传递的,可以求出方程 ax+by=gcd(a,b)的一组特解x, y
,并返回a,b
的最大公约数d
.
- 对于一般方程ax+by=c,它有解当且仅当其
d|c
,其中(d = gcd(a,b))
。
求解:
-
先求出
ax + by = d
的一组特解 x0,y0 -
x0,y0同时乘上 c/d,就是
ax + by = c
的一组特解:(c/d)x0,(c/d)y0. -
事实上,方程
ax + by = c
的通解可以表示为:
x=cdx0+kbd, y=cdy0−kad (k∈Z,d=gcd(a,b))
3. 线性同余方程
给定整数a,b,m 求一个整数 x 满足 a∗x≡b(modm), 或者给出无解。
-
a∗x≡b(modm) 改写成 a∗x+m∗y=b
-
根据
Bezout
定理,方程有解当且仅当 gcd(a,m)|b -
若有解,可通过拓展欧几里得算法求出 x0,y0, 满足 a∗x0+m∗y0=gcd(a,m)
-
然后,有 x=x0∗b/gcd(a,m) 就是原线性同余方程的一个特解
-
方程的通解为 x=x0∗bgcd(a,m)+kmgcd(a,m),(k∈Z)
4. 中国剩余定理
设 m1,m2,…,mn 是两两互质的整数,m = ∏ni=1mi , Mi = m/mi , ti 是线性同余方程 Miti≡1 (mod mi) 的一个解。对于任意的 n 个整数 a1,a2,…an ,方程组
{x≡a1(mod m1) x≡a2(mod m2) … x≡an(mod mn)
有整数解,解为 x=∑ni=1aiMiti。