zoukankan      html  css  js  c++  java
  • 素数的判断方法(从一般到高效)

    http://dongxicheng.org/structure/prime/

    1. 素数判定问题

      素数判定问题是一个非常常见的问题,本文介绍了常用的几种判定方法。

    2. 直观判断

      素数的定义是,除了能被1和它本身整除而不能被其他任何数整除的数。根据素数定义 只需要用2到n-1去除n,如果都除不尽,则n是素数,否则,只要其中有一个数能整除则n不是素数。

    1 bool prime_1(int n){
    2     for(int i=2;i<n;i++){
    3         if(n%i==0)
    4             return flase;//不是素数 
    5     }
    6     else
    7         return true;//是素数 
    8 }

    3. 直观判断改进

      上述判断方法,明显存在效率极低的问题。对于每个数n,其实并不需要从2判断到n-1,我们知道,一个数若可以进行因数分解,那么分解时得到的两个数一定是一个小于等于sqrt(n),一个大于等于sqrt(n),据此,上述代码中并不需要遍历到n-1,遍历到sqrt(n)即可,因为若sqrt(n)左侧找不到约数,那么右侧也一定找不到约数。C++代码如下:

    1 bool prime_2(int n){
    2     for(int i=2;i<=sqrt(n);i++)
    3         if(n%i==0)
    4             return flase;//不是素数 
    5         else
    6             return true;//是素数 
    7 }

    3. 筛法求素数

     更高效地素数判断方法应该是将素数预先保存到一个素数表中,当判断一个数是否为素数时,直接查表即可。这种方法需要解决两个问题:

     (1) 怎样快速得到素数表?(采用筛选方法)

     (2) 怎样减少素数表的大小?(采用位图数据结构)

     对于1到n全部整数,逐个判断它们是否是素数,找出一个非素数,就把它挖掉,最后剩下的就是素数。具体方法是:

     <1> 定义is_primer[i] = true;

     <2> 从2开始,依次遍历整个primer(直到sqrt(N)),如果primer[i]=true,则primer[n*i]=false

       如1,2,3,4,5,6,7,8,9,10,则

       从2开始遍历:

    primer[2]=true,则primer[4]= primer[6]= primer[8]= primer[10]= false,2的倍数

    primer[3]=true,则primer[6]= primer[9]= false,3的倍数

     1 #include<stdio.h>
     2 #define M 2000000
     3 char A[2000000]={""};
     4 int S[150001]={0};
     5 int main()
     6 {
     7     int m,n,i,j,k=0;
     8     for(i=2;i<M;i++)
     9         if(!A[i])
    10         {
    11             for(j=i+i;j<M;j+=i)
    12                 A[j]=1;
    13             S[++k]=i;
    14         }
    15         for(i=0;i<150001;i++)
    16             printf("%d	",S[i]);
    17         return 0;
    18 }

    哈希打表输出2000000以内的所有素数:

     1 //筛法求素数,哈希表查找
     2 #include<stdio.h>
     3 #define MAX 2000000
     4 int prime[2000000];
     5 int main(){
     6     for(int i=2;i<=MAX;i++) 
     7         prime[i]=1;
     8     prime[1]=0;
     9     for(int i=2;i<=MAX;i++)//打表 
    10             for(int j=2*i;j<=MAX;j+=i)
    11                 prime[j]=0;//偶数标记0 
    15     for(int i=2;i<=2000000;i++)
    16         if(prime[i]==1)
    17             printf("%d	",i);//输出素数
    18     return 0; 
    19 } 

    至今为止,没有任何人发现素数的分布规律,也没有人能用一个公式计算出所有的素数。关于素数的很多的有趣的性质或者科学家的努力,如:

    (1) 高斯猜测,n以内的素数个数大约与n/ln(n)相当,或者说,当n很大时,两者数量级相同。这就是著名的素数定理。

    (2) 十七世纪费马猜测,2的2^n次方+1,n=0,1,2…时是素数,这样的数叫费马素数,可惜当n=5时,2^32+1就不是素数,至今也没有找到第六个费马素数。

    (3) 18世纪发现的最大素数是2^31-1,19世纪发现的最大素数是2^127-1,20世纪末人类已知的最大素数是2^859433-1,用十进制表示,这是一个258715位的数字。

    (4) 孪生素数猜想:差为2的素数有无穷多对。目前知道的最大的孪生素数是1159142985×2^2304-1和1159142985×2^2304+1。

    (5) 歌德巴赫猜想:大于2的所有偶数均是两个素数的和,大于5的所有奇数均是三个素数之和。其中第二个猜想是第一个的自然推论,因此歌德巴赫猜想又被称为1+1问题。我国数学家陈景润证明了1+2,即所有大于2的偶数都是一个素数和只有两个素数因数的合数的和。国际上称为陈氏定理。(摘自《http://chuanbindeng.blog.163.com/blog/static/67886226200982892139468/》)

  • 相关阅读:
    LaTeX中表格多行显示的最简单设置方法
    获取Google音乐的具体信息(方便对Google音乐批量下载)
    移动硬盘提示格式化解决的方法,未正确删除导致不能读取文件提示格式化解决方式
    Android Service 服务(一)—— Service
    华为C8816电信版ROOT过程
    Linux crontab 命令格式与具体样例
    Python用subprocess的Popen来调用系统命令
    我的EJB学习历程
    接口和逻辑--多进程或单一进程
    uva 11354
  • 原文地址:https://www.cnblogs.com/geziyu/p/9287097.html
Copyright © 2011-2022 走看看