关键词:威尔逊定理 欧拉定理 费马小定理 中国剩余定理
威尔逊定理
当且仅当p为素数时,(p - 1)! ≡ -1 (mod p)
- 上式也可写作 (p - 1)! ≡ p-1 (mod p) 或 (p-1)! + 1 ≡ 0 (mod p)
- 上式可作素数的判别条件,但复杂度较大,实用性较差。
欧拉定理
若n,a为正整数,且n,a互质,即gcd(a,n) = 1,则
a^φ(n) ≡ 1 (mod n)
-
φ(n) 称欧拉函数,欧拉函数是求小于n的数中与n互质的数的数目
-
如果n是质数,那么1到n-1所有数都是与n互质的,所以φ(n) = n-1
-
如果n是合数,例如φ(8)=4,因为1,3,5,7均和8互质
-
欧拉函数求法:
- 基本原理:1到n-1中找到与n不互质的数,然后把他们减掉
- 具体操作*:找到n的质因子,把它们和它们的倍数都删掉
- 优化技巧:利用容斥原理避免重复处理
- 例子:φ(12)
- 找质因数:12 → \to → {2 3}
- 找倍数:[2] ≡ {2 4 6 8 10} 、[3] ≡ {3 6 9}
- 做统计:φ(12) = 12 - (12 / 2) - (12 / 3 ) + 1 = 12 * (1 - 1/2 - 1/3 + 1/6)
- 容斥优化:φ(12) = 12 * (1 - 1/2) * (1 - 1/3)
= 12 * (1 - 1/2 - 1/3 + 1/6)
-
欧拉定理可用于求逆元,显然 inv(a, n) = a ^ (φ(n) - 1)
实现代码
- 求单个欧拉函数(O(n^0.5)
//欧拉函数
int phi(int x){
int ans = x;
for(int i = 2; i*i <= x; i++){
if(x % i == 0){
ans = ans / i * (i-1);
while(x % i == 0) x /= i;
}
}
if(x > 1) ans = ans / x * (x-1);
return ans;
}
-
求n个欧拉函数(O(n))
注:类似于素数筛
#include<cstdio>
const int N = 100000 + 5;
int phi[N];
void Euler(){
phi[1] = 1;
for(int i = 2; i < N; i ++){
if(!phi[i]){
for(int j = i; j < N; j += i){
if(!phi[j]) phi[j] = j;
phi[j] = phi[j] / i * (i-1);
}
}
}
}
int main(){
Euler();
}
费马小定理
如果p是一个质数,而整数a不是p的倍数,则有a ^ (p - 1) ≡ 1(mod p)。
- 该定理可用于求逆元,显然 inv(a, p) = a ^ (p-2)
中国剩余定理
目标问题
求解线性同余方程组的最小整数解
\begin{cases}
x ≡ a_1 (mod m_1) \\
x ≡ a_2 (mod m_2) \\
...\\
x ≡ a_n (mod m_n) \\
\end{cases}
其中, m 1 m_1 m1、 m 2 m_2 m2、… 、 m n m_n mn为两两互质的整数
定理内容
令
M
=
∏
i
=
1
n
m
i
M=\prod_{i=1}^nm_i
M=∏i=1nmi,
M
i
=
M
/
m
i
M_i=M/m_i
Mi=M/mi,
t
i
=
i
n
v
(
M
i
,
m
i
)
t_i=inv(M_i,m_i)
ti=inv(Mi,mi),则方程组通解为
x
=
∑
i
=
1
n
a
i
t
i
M
i
+
k
M
,
k
∈
Z
x=\sum_{i=1}^{n}a_it_iM_i+kM, k \in Z
x=i=1∑naitiMi+kM,k∈Z
在模M意义下,方程唯一解为
x
=
∑
i
=
1
n
a
i
t
i
M
i
x=\sum_{i=1}^{n}a_it_iM_i
x=i=1∑naitiMi
简单证明
由逆元定义知
x
i
=
a
i
∗
t
i
M
i
=
a
i
∗
i
n
v
(
M
i
)
∗
M
i
=
a
i
∗
(
m
1
.
.
.
m
i
−
1
m
i
+
1
.
.
.
m
n
)
∗
i
n
v
(
(
m
1
.
.
.
m
i
−
1
m
i
+
1
.
.
.
m
n
)
)
≡
a
i
∗
1
(
m
o
d
m
i
)
≡
a
i
(
m
o
d
m
i
)
\begin{aligned} x_i&=a_i*t_iM_i \\ &=a_i*inv(M_i)*M_i \\ &=a_i*(m_1...m_{i-1}m_{i+1}...m_n)*inv((m_1...m_{i-1}m_{i+1}...m_n)) \\ &≡a_i*1 (mod \ mi) \\ &\equiv a_i(mod \ m_i) \end{aligned}
xi=ai∗tiMi=ai∗inv(Mi)∗Mi=ai∗(m1...mi−1mi+1...mn)∗inv((m1...mi−1mi+1...mn))≡ai∗1(mod mi)≡ai(mod mi)
故
a
i
∣
x
i
m
k
∣
x
i
,
k
≠
i
\begin{aligned} a_i\ &| \ x_i \\ m_k\ &| \ x_i\ ,\ k \neq i \end{aligned}
ai mk ∣ xi∣ xi , k=i
即
x
i
≡
a
i
(
m
o
d
m
i
)
x
i
≡
0
(
m
o
d
M
k
)
,
k
≠
i
\begin{aligned} x_i &\equiv a_i (mod \ m_i) \\ x_i &\equiv 0 \ (mod \ M_k)\ ,\ k \neq i \end{aligned}
xixi≡ai(mod mi)≡0 (mod Mk) , k=i
令
x
=
∑
i
=
1
n
x
i
x=\sum_{i=1}^{n}x_i
x=i=1∑nxi
则
x
%
m
i
=
(
x
1
+
.
.
.
+
x
i
+
.
.
.
+
x
n
)
%
m
i
=
(
x
1
%
m
i
+
.
.
.
+
x
i
%
m
i
+
x
n
%
m
i
)
%
m
i
=
(
0
+
.
.
.
+
a
i
+
.
.
.
+
0
)
=
a
i
\begin{aligned} x \ \% \ m_i &= (x_1+...+x_i+...+x_n) \ \% \ m_i \\ &= (x_1 \ \% \ m_i + ... + x_i \ \% \ m_i + x_n \ \% \ m_i) \ \% \ m_i \\ &= (0+...+a_i+...+0) \\ &=a_i \end{aligned}
x % mi=(x1+...+xi+...+xn) % mi=(x1 % mi+...+xi % mi+xn % mi) % mi=(0+...+ai+...+0)=ai
即
x
≡
a
i
(
m
o
d
m
i
)
x \equiv a_i (mod \ m_i)
x≡ai(mod mi)
实现代码
//n个方程:x=a[i](mod m[i]) (0<=i<n)
LL china(int n, LL *a, LL *m){
LL M = 1, ret = 0;
for(int i = 0; i < n; i ++) M *= m[i];
for(int i = 0; i < n; i ++){
LL w = M / m[i];
ret = (ret + w * inv(w, m[i]) * a[i]) % M;
}
return (ret + M) % M;
}
参考博客
- https://www.cnblogs.com/linyujun/p/5194142.html