• 威尔逊定理


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

             定理内容:当( 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+2

         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之间的素数用筛法筛出来,然后直接线性时间内输出结果即可。

    代码如下:

     1 #include <cstdio>
     2 #include <cstring>
     3 
     4 const int MAXN = 1e6+10;
     5 bool u[3*MAXN];                       //若i为素数则标记为1.;之所以乘3,是为了保证筛得的数够u[3*i+7]用 
     6 int prime[3*MAXN], cnt = 0;           //cnt记录素数个数 
     7 int ans[MAXN], t, n;
     8 
     9 int main()
    10 {
    11     memset(u, true, sizeof(u));
    12     
    13     //这一步的核心是筛法求素数 
    14     for(int i=2; i<3*MAXN; ++i)
    15     {
    16         if(u[i]) prime[cnt++] = i;    //用prime数组记录素数 
    17         for(int j=0; j<cnt && i*prime[j]<3*MAXN; ++j)
    18         {
    19             u[i*prime[j]] = false;    //把素数prime[j]的i倍的数全部筛掉   
    20             if(0 == i%prime[j]) break;//符合该条件的i已经标志prime[i]=0,故无需重复标记   
    21         }
    22     }
    23     
    24     //这一步的核心是威尔逊定理,可以推出简单化结论 
    25     ans[0] = 0;
    26     for(int i=1; i<MAXN; ++i)
    27     {
    28         ans[i] = ans[i-1] + u[3*i+7];//若3i+7为素数,则该项的值为1,就在Sn=S(n-1)+1. 
    29     }
    30  
    31     scanf("%d", &t);
    32     while(t--)
    33     {
    34         scanf("%d", &n);
    35         printf("%d
    ", ans[n]);
    36     }
    37     return 0;
    38 }
  • 相关阅读:
    SQL作业的操作全
    ISAPI Rewrite 实现简单url重写、二级域名重写
    wwf mvc学习
    如何扩大内需
    惊喜
    无限级分类查询
    杂记
    20130118SQL记录
    百度调价HttpWebRequest
    检查外链的方法
  • 原文地址:https://www.cnblogs.com/liugl7/p/4896914.html
Copyright © 2020-2023  润新知