一、介绍
1.内容
p 是质数的充要条件为
(
p
−
1
)
!
≡
−
1
(
m
o
d
p
)
(p−1)! ≡ −1 (mod p)
(p−1)!≡−1(modp)
也可以写作:p为质数的充要条件为
p
∣
(
p
−
1
)
!
+
1
p∣(p−1)!+1
p∣(p−1)!+1
2.适用情况
可以用于直接判断p是否为质数,但由于涉及阶乘操作,所以很少使用。
二、证明
1.必要性
已知 p ∣ ( p − 1 ) ! + 1 p∣(p−1)!+1 p∣(p−1)!+1,证明p为质数
既然有 ( p − 1 ) ! (p−1)! (p−1)!出现,说明p>1。
反证法:若p不为质数,则p存在一个质因数d, p = u d ( 2 < = d < = p − 1 ) p=ud(2<=d<=p-1) p=ud(2<=d<=p−1);
已知
d
∣
(
p
−
1
)
!
d∣(p−1)!
d∣(p−1)!必定成立,原式可以写为
(
p
−
1
)
!
+
1
=
v
d
+
1
(p−1)!+1=vd+1
(p−1)!+1=vd+1
原式又存在关系
(
p
−
1
)
!
+
1
=
k
p
=
k
u
d
(p−1)!+1=kp=kud
(p−1)!+1=kp=kud
两式不会相等,产生矛盾,故p一定为一个质数。
2.充分性
已知p为质数,证明 p ∣ ( p − 1 ) ! + 1 p∣(p−1)!+1 p∣(p−1)!+1
当p等于2时,
(
2
−
1
)
!
+
1
(2-1)!+1
(2−1)!+1等于2,成立;
当p等于3时,
(
3
−
1
)
!
+
1
(3-1)!+1
(3−1)!+1等于3,成立;
当p>=5时,可以借助逆元性质进行推理。
逆元性质:当p为素数,则 1~p-1 的所有整数的 模p逆元 对应1~p-1的所有整数,既是单射也是满射,而且1跟p-1对应的模p逆元都是本身。
例如,当p=7时,1~6 对应的 模7逆元 分别是 1,4,5,2,3,6
那么也就意味着再[2,p-2]中是一一配对的,
(
p
−
2
)
!
(p-2)!
(p−2)!的值与1在模p的情况下同余。
也就是
(
p
−
2
)
!
=
k
p
+
1
(p-2)!=kp+1
(p−2)!=kp+1
所以
(
p
−
1
)
!
+
1
=
(
p
−
2
)
!
∗
(
p
−
1
)
+
1
=
(
k
p
+
1
)
(
p
−
1
)
+
1
=
t
p
(p-1)!+1=(p-2)!*(p-1)+1=(kp+1)(p-1)+1=tp
(p−1)!+1=(p−2)!∗(p−1)+1=(kp+1)(p−1)+1=tp
所以可以证明当p为质数时,有
p
∣
(
p
−
1
)
!
+
1
p∣(p−1)!+1
p∣(p−1)!+1。
二、例题·YAPTCHA
1.大意
由给定的n计算这个累加的和。
2.分析
由给定的形式,可以联想到威尔逊定理中的式子
注意求整运算符的存在
-
当 ( 3 k + 7 ) (3k+7) (3k+7)为质数时
恰满足条件 p ∣ ( p − 1 ) ! + 1 p∣(p−1)!+1 p∣(p−1)!+1,而且 [ ( p − 1 ) ! p ] = ( p − 1 ) ! + 1 p − 1 [\frac{(p-1)!}{p}]=\frac{(p-1)!+1}{p}-1 [p(p−1)!]=p(p−1)!+1−1
小小的证明:
由上方证明可知 ( p − 2 ) ! = k p + 1 (p-2)!=kp+1 (p−2)!=kp+1,那么 ( p − 1 ) ! = ( p − 2 ) ! ( p − 1 ) = k p 2 − k p + p − 1 (p-1)!=(p-2)!(p-1)=kp^2-kp+p-1 (p−1)!=(p−2)!(p−1)=kp2−kp+p−1,所以 [ ( p − 1 ) ! p ] [\frac{(p-1)!}{p}] [p(p−1)!]等于 k p − k kp-k kp−k,也就是 ( p − 1 ) ! + 1 p − 1 \frac{(p-1)!+1}{p}-1 p(p−1)!+1−1的结果了。
所以此时结果为1 -
当 ( 3 k + 7 ) (3k+7) (3k+7)不为质数时
( p − 1 ) ! + 1 p − ( p − 1 ) ! p = ( p − 1 ) ! p + 1 p − ( p − 1 ) ! p = 1 p \frac{(p-1)!+1}{p}-\frac{(p-1)!}{p}=\frac{(p-1)!}{p}+\frac{1}{p}-\frac{(p-1)!}{p}=\frac{1}{p} p(p−1)!+1−p(p−1)!=p(p−1)!+p1−p(p−1)!=p1
,通过取整操作,结果取0
结果就是对范围内的质数进行计数。
单纯的遍历计数会超时,所以可以将所有满足格式3k+7的数统一存入一个数组,再处理为前缀和,方便进行多次的区间访问。
3.代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=3e6+50;
int a[N];
int cnt=0;
int p[N];
void f(int n){
for(int i=2;i<=n;i++){
if(!p[i])a[cnt++]=i;
for(int j=0;j<cnt&&i*a[j]<=n;j++){
p[i*a[j]]=1;
if(i%a[j]==0)break;
}
}
}
int main(){
f(N-1);
int t;
memset(a,0,sizeof a);
p[0]=p[1]=1;
for(int i=1;i<1e6+5;i++){
a[i]=(p[3*i+7]+1)%2;
a[i]+=a[i-1];
}
cin>>t;
while(t--){
int n;
cin>>n;
cout<<a[n]-a[1]<<endl;
}
}