zoukankan      html  css  js  c++  java
  • 质数筛法 nsqrt(n)/nloglog(n)/n

    数论第一篇随笔,就讲一下质数筛法吧

    质数,也称做素数,在数学中有着重要的地位,有很多问题与算法都与质数有关(比如给你的hash函数选择一个好的质数可以让你的RP++)。对质数的最基本操作,就是输出所有不大于n(n∈N*)的素数

    最简单的方法:首先逐个枚举从 2 ~ n 的数a,分别模 2 ~ sqrt(a)(即a的平方,想一下为什么只需要判到sqrt(a)),若余数为0,那么a不是质数。

    实现代码:

     1 #include<stdio.h>
     2 #include<math.h>
     3 int n;
     4 int main(){
     5     scanf("%d",&n);
     6     if(n<2){
     7         printf("0");
     8         return 0;
     9     }
    10     for(int i=2;i<=n;i++){
    11         bool f=true;
    12         for(int j=2;j<=sqrt(i);j++)
    13            if(i%j==0){
    14                f=false;
    15                break;
    16            }
    17         if(f) printf("%d ",i);
    18     }
    19     return 0;
    20 }
    朴素算法

    以上朴素算法复杂度为O(nsqrt(n))

    既然叫做朴素算法,那肯定有效率比它高的算法,那就是筛法求质数

    它是通过划掉n内每个已求出质数的所有倍数来实现,留下来的数就都是不大于n的质数

    举个例子,我们要求不大于15的所有质数:                     1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

    1不是质数,2是最小的质数,从2开始划掉2的倍数:             1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

    轮到3,3没有被划掉,是质数,所以划掉3的倍数:              1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

    然后依次是5、7、11、13,重复上面的步骤。

    其实这种情况下在划掉所有3的倍数时就已经求出了所有不大于15的质数,即没有被划掉的数

    实现代码:

     1 #include<stdio.h>
     2 #include<string.h>
     3 #define maxn 2333333
     4 int n;
     5 bool zs[maxn];
     6 int main(){
     7     memset(zs,0,sizeof(zs));
     8     scanf("%d",&n);
     9     zs[0]=zs[1]=1;
    10     for(int i=2;i*i<=n;i++)//i<=sqrt(n) ===>  i*i<=n
    11        if(!zs[i])
    12            for(int j=i+i;j<=n;j+=i) 
    13         zs[j]=1;
    14     for(int i=2;i<=n;i++)
    15        if(!zs[i]) 
    16        printf("%d ",i);
    17     return 0;
    18 }
    质数筛法

    这种做法的算法复杂度为O(nloglog(n))

    那有没有比以上效率更高的做法呢,有的!

    如果按以上方法做,会有计算冗余,比如60这个数,会被2,3,5各筛一次

    所有就有了下面复杂度为O(n)的方法

    实现代码:

     1 #include<stdio.h>
     2 #include<string.h>
     3 #define maxn 2333333
     4 bool zs[maxn];
     5 int n,prime[maxn],num;
     6 int main(){
     7     memset(zs,0,sizeof(zs));
     8     scanf("%d",&n);
     9     zs[0]=zs[1]=1;num=0;
    10     for(int i=2;i<=n;i++){
    11         if(!zs[i]){
    12             prime[++num]=i;
    13             printf("%d ",prime[num]);
    14         }
    15         for(int j=1;j<=num&&i*prime[j]<=n;j++){
    16             zs[i*prime[j]]=1;
    17             if(!(i%prime[j])) break;
    18         }
    19     }
    20     return 0;
    21 }
    质数的线性筛

    这种方法就叫质数的线性筛法

    详细的以后再讲吧

  • 相关阅读:
    商户编号前三位代码对应的收单机构大全
    使用邮件模板(freemarker.jar)发送邮件
    Struts2自定义拦截器
    如何在jsp页面显示存储在数据库的图片
    正则表达式 大于0的数字(包含小数)
    Linux的关机命令
    maven的下载和安装
    web.py的安装
    安装第三方插件BeautifulSoup
    myeclipse离线安装pydev插件
  • 原文地址:https://www.cnblogs.com/lpl-bys/p/7726113.html
Copyright © 2011-2022 走看看