一、威尔逊定理内容及证明
内容
p p p 质数当且仅当 ( p − 1 ) ! ≡ − 1 ( m o d p ) (p-1)!\equiv-1\pmod p (p−1)!≡−1(modp) 。
证明
(1)充分性
即 p p p 是质数,则 ( p − 1 ) ! ≡ − 1 ( m o d p ) (p-1)!\equiv-1\pmod p (p−1)!≡−1(modp) 。
我们知道,在模奇素数
p
p
p 的剩余系下,
1
1
1 到
p
−
1
p-1
p−1 的逆元都存在。考虑到
x
x
−
1
≡
1
(
m
o
d
p
)
xx^{-1}\equiv 1\pmod p
xx−1≡1(modp) ,原式可化简为:
(
p
−
1
)
!
=
Π
i
−
1
≠
i
i
×
Π
i
−
1
=
i
i
≡
Π
i
−
1
=
i
i
(
m
o
d
p
)
(p-1)!= \Pi_{i^{-1}\neq i} i\times \Pi_{i^{-1}=i}i\equiv\Pi_{i^{-1}=i}i\pmod p
(p−1)!=Πi−1=ii×Πi−1=ii≡Πi−1=ii(modp)
因此需要考虑哪些数的逆元是其本身,即满足二次剩余
x
2
≡
1
(
m
o
d
p
)
x^2\equiv1\pmod p
x2≡1(modp) 。移向后因式分解可得
(
x
−
1
)
(
x
+
1
)
≡
0
(
m
o
d
p
)
(x-1)(x+1)\equiv0\pmod p
(x−1)(x+1)≡0(modp)
解得 x = ± 1 x=\pm1 x=±1 。
在 1 1 1 到 p − 1 p-1 p−1 这 p − 1 p-1 p−1 个数中,除了 1 1 1 和 p − 1 p-1 p−1 的逆元是本身外,对于 ∀ x ∈ [ 2 , p − 2 ] , ∃ y ∈ [ 2 , p − 2 ] \forall x\in [2,p-2],\exist y\in [2,p-2] ∀x∈[2,p−2],∃y∈[2,p−2] 满足 x y ≡ 1 ( m o d p ) xy\equiv 1\pmod p xy≡1(modp) 且 y ≠ x y\neq x y=x 。
综上, Π i − 1 = i i = 1 × ( p − 1 ) ≡ − 1 ( m o d p ) \Pi_{i^{-1}=i}i=1\times(p-1)\equiv-1\pmod p Πi−1=ii=1×(p−1)≡−1(modp) 。
(2)必要性
即 ( p − 1 ) ! ≡ − 1 ( m o d p ) (p-1)!\equiv-1\pmod p (p−1)!≡−1(modp),则 p p p 是质数。直接证明有些困难,因此采用反证法,假设 p p p 满足条件且为合数,推出矛盾“任何合数都不可能满足这个条件”。
① p = 1 p=1 p=1
此时 ( p − 1 ) ! = 0 ! = 1 ≡ 0 ( m o d 1 ) (p-1)!=0!=1\equiv0\pmod 1 (p−1)!=0!=1≡0(mod1) ,不满足上述条件。
② p = 4 p=4 p=4
此时 ( p − 1 ) ! = 3 ! = 6 ≡ 2 ( m o d 4 ) (p-1)!=3!=6\equiv2\pmod 4 (p−1)!=3!=6≡2(mod4) ,不满足上述条件。
③ p > 4 p>4 p>4 且 p p p 是完全平方数
不妨设
p
=
k
2
p=k^2
p=k2 ,显然
k
>
2
k>2
k>2 。做差易得
p
>
2
k
p>2k
p>2k 。
那么有
(
p
−
1
)
!
=
1
×
⋯
×
k
×
⋯
×
2
k
×
⋯
×
(
p
−
1
)
=
2
k
2
×
(
…
)
(p-1)!=1\times \dots\times k\times\dots\times2k\times \dots\times (p-1)=2k^2\times(\dots)
(p−1)!=1×⋯×k×⋯×2k×⋯×(p−1)=2k2×(…)
为 p p p 的整数倍,因此 ( p − 1 ) ! ≡ 0 ( m o d p ) (p-1)!\equiv0\pmod p (p−1)!≡0(modp) 。
④ p > 4 p>4 p>4 且 p p p 不是完全平方数
由于
p
p
p 不是完全平方数且不是质数,不妨设
p
=
a
×
b
,
a
<
b
p=a\times b,a< b
p=a×b,a<b 。
那么有
(
p
−
1
)
!
=
1
×
⋯
×
a
×
⋯
×
b
×
⋯
×
(
p
−
1
)
=
(
a
×
b
)
×
(
…
)
(p-1)!=1\times\dots\times a\times\dots\times b\times \dots\times(p-1)=(a\times b)\times(\dots)
(p−1)!=1×⋯×a×⋯×b×⋯×(p−1)=(a×b)×(…)
为 p p p 的整数倍,因此 ( p − 1 ) ! ≡ 0 ( m o d p ) (p-1)!\equiv0\pmod p (p−1)!≡0(modp) 。
二、例题和代码
(1) HDU2973 YAPTCHA
题目大意:
共
T
T
T 组数据,求
∑
k
=
1
n
⌊
(
3
k
+
6
)
!
+
1
(
3
k
+
7
)
−
⌊
(
3
k
+
6
)
!
(
3
k
+
7
)
⌋
⌋
\sum_{k=1}^{n}\Big\lfloor\frac{(3k+6)!+1}{(3k+7)}-\big\lfloor\frac{(3k+6)!}{(3k+7)}\big\rfloor\Big\rfloor
k=1∑n⌊(3k+7)(3k+6)!+1−⌊(3k+7)(3k+6)!⌋⌋
的值( T , n ⩽ 1 0 6 T,n\leqslant10^6 T,n⩽106)。
题解
威尔逊定理模板题。
令
3
k
+
7
=
x
3k+7=x
3k+7=x 得:
原
式
=
∑
k
=
1
n
⌊
(
x
−
1
)
!
+
1
x
−
⌊
(
x
−
1
)
!
x
⌋
⌋
原式=\sum_{k=1}^{n}\Big\lfloor\frac{(x-1)!+1}{x}-\big\lfloor\frac{(x-1)!}{x}\big\rfloor\Big\rfloor
原式=k=1∑n⌊x(x−1)!+1−⌊x(x−1)!⌋⌋
当
x
x
x 为质数时,根据威尔逊定理有
(
x
−
1
)
!
≡
−
1
(
m
o
d
x
)
(x-1)!\equiv -1\pmod x
(x−1)!≡−1(modx) ,即
(
x
−
1
)
!
+
1
≡
0
(
m
o
d
x
)
(x-1)!+1\equiv0\pmod x
(x−1)!+1≡0(modx) ,故
x
∣
(
x
−
1
)
!
+
1
x\mid(x-1)!+1
x∣(x−1)!+1 ,因此
(
x
−
1
)
!
+
1
x
−
⌊
(
x
−
1
)
!
x
⌋
=
1
\frac{(x-1)!+1}{x}-\big\lfloor\frac{(x-1)!}{x}\big\rfloor=1
x(x−1)!+1−⌊x(x−1)!⌋=1
当
x
x
x 不是质数时,在证明威尔逊定理的必要性时有
∀
x
>
4
,
(
x
−
1
)
!
≡
0
(
m
o
d
x
)
\forall x > 4,(x-1)!\equiv0\pmod x
∀x>4,(x−1)!≡0(modx) ,因此
x
∣
(
x
−
1
)
!
x\mid(x-1)!
x∣(x−1)! ,因此
⌊
(
x
−
1
)
!
+
1
x
−
⌊
(
x
−
1
)
!
x
⌋
⌋
=
0
\Big\lfloor\frac{(x-1)!+1}{x}-\big\lfloor\frac{(x-1)!}{x}\big\rfloor\Big\rfloor=0
⌊x(x−1)!+1−⌊x(x−1)!⌋⌋=0
综上,所求的式子可以化简为
原
式
=
∑
k
=
1
n
[
x
is prime
]
=
∑
k
=
1
n
[
3
k
+
7
is prime
]
原式=\sum_{k=1}^{n}\big[x\text{ is prime}\big]=\sum_{k=1}^{n}[3k+7\text{ is prime}]
原式=k=1∑n[x is prime]=k=1∑n[3k+7 is prime]
使用筛法筛出素数后统计前缀和即可,代码如下。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 3e6 + 10;
bool vist[maxn];
int cnt;
int sum[maxn], prime[maxn];
int T, n;
void Euler(int n){
vist[1] = true;
for (int i = 2; i <= n; i ++){
if (!vist[i]) prime[++ cnt] = i;
for (int j = 1; j <= cnt && i * prime[j] <= n; j ++){
vist[i * prime[j]] = true;
if (prime[j] % i == 0) break;
}
}
for (int i = 1; i < maxn; i ++) sum[i] = sum[i - 1] + (vist[3 * i + 7] == 0);
}
int main(){
Euler(maxn - 1);
cin >> T;
while (T --){
cin >> n;
cout << sum[n] << endl;
}
return 0;
}
(2) HDU6608
题目大意:
共
T
T
T 组数据,给定质数
p
p
p ,求小于
p
p
p 的最大质数
q
q
q 并求下式的值(
T
⩽
10
,
1
0
9
⩽
p
⩽
1
0
14
T\leqslant 10,10^9\leqslant p\leqslant 10^{14}
T⩽10,109⩽p⩽1014)。
q
!
m
o
d
p
q! \bmod p
q!modp
题解
由威尔逊定理
(
p
−
1
)
!
≡
−
1
(
m
o
d
p
)
(p-1)!\equiv-1\pmod p
(p−1)!≡−1(modp)
推导得
q
!
×
(
q
+
1
)
×
(
q
+
2
)
×
⋯
×
(
p
−
1
)
≡
−
1
(
m
o
d
p
)
q!\times(q+1)\times(q+2)\times\dots\times (p-1)\equiv-1\pmod p
q!×(q+1)×(q+2)×⋯×(p−1)≡−1(modp)
q
!
≡
−
(
q
+
1
)
−
1
(
q
+
2
)
−
1
×
⋯
×
(
p
−
1
)
−
1
(
m
o
d
p
)
q!\equiv-(q+1)^{-1}(q+2)^{-1}\times\dots\times(p-1)^{-1}\pmod p
q!≡−(q+1)−1(q+2)−1×⋯×(p−1)−1(modp)
因此从
p
−
1
p-1
p−1 开始倒序枚举,使用朴素的质数检验方法检验是否为质数并记录逆元的累乘,枚举到质数就输出并停止。不过观察到数据范围比较大,因此需要使用龟速乘,代码如下。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e7 + 5;
bool vist[maxn];
int cnt;
int prime[1000005];
void Euler(int n){
for (int i = 2; i <= n; i ++){
if (!vist[i]) prime[++ cnt] = i;
for (int j = 1; j <= cnt && i * prime[j] <= n; j ++){
vist[i * prime[j]] = true;
if (i % prime[j] == 0) break;
}
}
}
int T;
long long n;
bool is_prime(long long x){
for (int i = 1; i <= cnt && prime[i] * prime[i] <= x; i ++)
if (x % prime[i] == 0) return false;
return true;
}
long long sMul(long long a, long long b, long long MOD){
long long ans = 0;
while (b){
if (b & 1) ans = (ans + a) % MOD;
a = (a + a) % MOD;
b >>= 1;
}
return ans;
}
long long qPow(long long a, long long b, long long MOD){
long long ans = 1;
while (b){
if (b & 1) ans = sMul(ans, a, MOD);
a = sMul(a, a, MOD);
b >>= 1;
}
return ans;
}
long long get_inv(long long a, long long p){
return qPow(a, p - 2, p);
}
int main(){
std::ios::sync_with_stdio(false);
cin.tie(0);
Euler(maxn - 1);
cin >> T;
while (T --){
cin >> n;
long long ans = n - 1;
for (long long i = n - 1; ; i --){
bool ret = is_prime(i);
if (ret){
cout << ans << '\n';
break;
}
ans = sMul(ans, get_inv(i, n), n);
}
}
return 0;
}