您的位置:首页 > 其它

威尔逊定理

2015-10-21 09:39 155 查看
讲解过素数判定之后,老师又讲了一个威尔逊定理,挺有意思的,竟然是判断素数的定理,还是充分必要条件!。。然并卵,判定增长是指数级的,并没有什么实用价值。。不过还是总结一下这个学院派的定理吧。。。。也不知道猴年马月能用上,不过多知道一条定理总是好的!

定理内容:当( p -1 )! ≡ -1 ( mod p ) 时,p为素数。其逆定理也正确。定理的证明这里从略,下面主要讲一下它的应用。

根据威尔逊定理,想要判断一个数是否是素数,只需要从1到比该数小1的数统统乘起来,然后加1,得到的和如果能整除该数,则该数就是一个素数。这个判定方法虽然是判定素数的充要条件,但是并没有太多的实用价值:其判定时需要的计算量成指数级增长。例如判定41243是否是一个素数,就需要计算1*2*3*4...41241*41242.且不说乘法计算下来的时间问题了,就是想找一个空间存储计算得到的值就是一个几乎难以解决的问题。

   不过关于威尔逊定理有一些推论:形如4x+1的质数,一定可以表示为两个整数的平方和,而且表达方法是唯一的;

而形如4x-1的质数,不可能是两个整数的平方和。

-----------------------------------------

质数  4x+1型=a2+b2 4x-1型

  3       4×1-1

5 4×1+1=22+12

  7       4×2-1

11            4×3-1

  13 4×3+1=32+22

  17  4×4+1=42+12

19            4×5-1

23            4×6-1

29  4×7+1=52+22

31           4×8-1

37 4×9+1=62+12

41 4×10+1=52+42

43           4×11-1

------------------------------------------

我们知道大于3的奇数都能写成4x+1和4x-1(其实就是4k+3) 的形式,所以,威尔逊定理的这个推论,覆盖了2以外所有的质数!这大大的增加了人们对素数的认识程度!

曝一道习题吧:威尔逊定理的应用。

HDU 2973 YAPTCHA

此题运用威尔逊定理分析之后,实际上求得是1~n之间素数的个数,由于题目中t的值较大,这里可以先将1~106之间的素数用筛法筛出来,然后直接线性时间内输出结果即可。

代码如下:

#include <cstdio>
#include <cstring>

const int MAXN = 1e6+10;
bool u[3*MAXN];                       //若i为素数则标记为1.;之所以乘3,是为了保证筛得的数够u[3*i+7]用
int prime[3*MAXN], cnt = 0;           //cnt记录素数个数
int ans[MAXN], t, n;

int main()
{
memset(u, true, sizeof(u));

//这一步的核心是筛法求素数
for(int i=2; i<3*MAXN; ++i)
{
if(u[i]) prime[cnt++] = i;    //用prime数组记录素数
for(int j=0; j<cnt && i*prime[j]<3*MAXN; ++j)
{
u[i*prime[j]] = false;    //把素数prime[j]的i倍的数全部筛掉
if(0 == i%prime[j]) break;//符合该条件的i已经标志prime[i]=0,故无需重复标记
}
}

//这一步的核心是威尔逊定理,可以推出简单化结论
ans[0] = 0;
for(int i=1; i<MAXN; ++i)
{
ans[i] = ans[i-1] + u[3*i+7];//若3i+7为素数,则该项的值为1,就在Sn=S(n-1)+1.
}

scanf("%d", &t);
while(t--)
{
scanf("%d", &n);
printf("%d\n", ans
);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: