质数筛法 nsqrt(n)/nloglog(n)/n

Posted lpl_bys

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了质数筛法 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 }
质数的线性筛

 

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

详细的以后再讲吧

以上是关于质数筛法 nsqrt(n)/nloglog(n)/n的主要内容,如果未能解决你的问题,请参考以下文章

51NOD 1181 质数中的质数(质数筛法)

51nod 1181 质数中的质数(质数筛法)

51Nod 1181 质数中的质数(质数筛法)

51Nod - 1181 质数中的质数(质数筛法)

1181 质数中的质数(质数筛法)(51NOD基础)

欧拉筛——$Theta(n)$复杂度的质数筛法