在介绍威尔逊定理之前,我们先给出一个引理:
如果
p
p
p是素数,正整数
a
a
a是其自身模
p
p
p的逆,当且仅当
a
≡
1
(
m
o
d
p
)
a\equiv1(mod\ p)
a≡1(mod p)或者
a
≡
−
1
(
m
o
d
p
)
a\equiv{-}1(mod\ p)
a≡−1(mod p).
证明:如果
a
≡
1
(
m
o
d
p
)
a\equiv1(mod\ p)
a≡1(mod p)或
a
≡
−
1
(
m
o
d
p
)
a\equiv{-}1(mod\ p)
a≡−1(mod p),则
a
2
≡
1
(
m
o
d
p
)
a^2\equiv1(mod\ p)
a2≡1(mod p), 所以
a
a
a是其自身模
p
p
p的逆。反之,如果
a
a
a是其自身模
p
p
p的逆,即
a
2
≡
1
(
m
o
d
p
)
a^2\equiv1(mod\ p)
a2≡1(mod p),则
(
a
2
−
1
)
m
o
d
p
=
0
(a^2-1)\ mod\ p=0
(a2−1) mod p=0,因为
p
p
p是素数,所以
(
a
−
1
)
m
o
d
p
=
0
(a-1)\ mod\ p=0
(a−1) mod p=0或者
(
a
+
1
)
m
o
d
p
=
0
(a+1)\ mod\ p=0
(a+1) mod p=0,因此
a
≡
1
(
m
o
d
p
)
a\equiv1(mod\ p)
a≡1(mod p)或
a
≡
−
1
(
m
o
d
p
)
a\equiv{-}1(mod\ p)
a≡−1(mod p).
接着,我们再给出威尔逊定理的定义:
威尔逊定理 (Wilson’s Theorem):如果
p
p
p是素数,则
(
p
−
1
)
!
≡
−
1
(
m
o
d
p
)
(p-1)!\equiv-1(mod\ p)
(p−1)!≡−1(mod p).
证明过程参考这里:威尔逊定理的证明
同时,威尔逊定理的逆也是成立的,它可以这么表述:
设
p
p
p是正整数且
p
≥
2
p\ge2
p≥2,如果
(
p
−
1
)
!
≡
−
1
(
m
o
d
p
)
(p-1)!\equiv-1(mod\ p)
(p−1)!≡−1(mod p),则
p
p
p是素数。
显然威尔逊定理在计算机邻域的最大作用就是给出了一个素数判定的条件,光说不练假把式,下面我们将展示一道例题来真正了解下,威尔逊定理的使用。
ACM Central European Programming Contest 2008(HDOJ 2973)
这道题的大体题意是:求出这个表达式的值
我们很容易看出来这个
3
k
+
6
3k+6
3k+6和
3
k
+
7
3k+7
3k+7就差了1,而
3
k
+
6
3k+6
3k+6又是阶乘的形式,非常明显的一个威尔逊定理的应用,
求解这道题时我们我们先判断
3
k
+
7
3k+7
3k+7是不是素数,对于单个表达式而言,是素数的话值为1,不是则为0;
那么我们直接打表计算前缀和就ok。
AC代码如下:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn = 1e5+5;
int ans[maxn];
bool isprime(int n)
{
if(n%2 == 0)
return false;
for(int i=3;i*i<=n;i++)
{
if(n % i== 0)
return false;
}
return true;
}
int main()
{
int case;
cin >> case;
ans[0] = 0;
for(int i=1;i<maxn;i++) //打表
{
if(isprime(3*i+7))
ans[i] = ans[i-1]+1;
else
ans[i] = ans[i-1];
}
while(case--)
{
int n;
scanf("%d", &n);
printf("%d\n",ans[n]);
}
}