威尔逊定理给出了判定一个自然数是否为质数的充分必要条件。
即当且仅当p为质数时:
威尔逊定理的证明
充分性证明:
若p不是质数
当p=4时,(p-1)!≡6≡2(mod p)
当p>4时
若p不是完全平方数
令p = a × b,1<a<b<p,则有
则(p-1)!≡0(mod p)
若p是完全平方数
令p=k^2,又p > 4,所以k > 2,2k<p,则有
则(p-1)!≡0(mod p)
必要性证明:
若p是质数,则取集合A={1,2,3,...,p-1} 是模p的简化剩余系
对任意的i∈A,存在j∈A,使得i与j互质,那么A中元素是否能恰好两两配对
考虑x^2≡1(mod p),则x≡1(mod p)或x≡p-1(mod p)
那么剩下的一定两两配对,所以有
(p-1)!≡1*(p-1)≡-1(mod p)
证毕。
由上我们从威尔逊定理中得到两个推论:
- 若p是质数,则(p-1)!+1≡0(mod p)
- 若p不是质数并且p>4,则(p-1)!≡0(mod p)
来看道例题 YAPTCHA - HDU 2973 - Virtual Judge (vjudge.net)
我们可以对这个式子进行拆分构造威尔逊定理的形式
令p=3k+7,则求和式变为
若p为质数,由威尔逊定理的推论1可知是整数 ,那么可知
比
小1,所以
若p不为质数,则为整数,所以
那么接下来就很简单了,只需要把[1,3000007]的质数筛出,那么答案就是[1,n]中符合3k+7形式的质数个数即可。
代码如下
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 3e6 + 7, M = 1e6 + 9;
int a[N], ans[N];
bool vis[N];
void fun(){
for(LL i = 2; i <= N; i++){
if(!vis[i]){
if((i - 7) % 3 == 0) {
a[(i - 7) / 3] = 1;
}
}
for(LL j = i * i; j <= N; j += i){
vis[j] = 1;
}
}
}
int main(){
fun();
for(int i = 2; i <= M; i++){
ans[i] = ans[i - 1] + a[i];
}
int t;
scanf("%d", &t);
while(t--){
int n;
scanf("%d", &n);
printf("%d\n", ans[n]);
}
return 0;
}