线性筛法求素数

 

题目

给定一个正整数 n,请你求出 1∼n 中质数的个数。

输入格式

共一行,包含整数 n

输出格式

共一行,包含一个整数,表示 1n中质数的个数。

数据范围

1n1e6

输入样例:

8

输出样例:

4
 

 

埃氏筛法

时间复杂度:O(nloglogn)

思路:

 (1)先把1删除(现今数学界1既不是质数也不是合数)

(2)读取队列中当前最小的数2,然后把2的倍数删去

(3)读取队列中当前最小的数3,然后把3的倍数删去

(4)读取队列中当前最小的数5,然后把5的倍数删去

(5)读取队列中当前最小的数7,然后把7的倍数删去

(6)如上所述直到需求的范围内所有的数均删除或读取

代码:

复制代码
 1 #include<iostream>
 2 using namespace std;
 3 const int N=1e6+10;
 4 int prime[N],cnt;
 5 bool st[N];
 6 void get_prime(int n)
 7 {
 8     for(int i=2;i<=n;i++)
 9     {
10         if(!st[i])
11         {
12             prime[cnt++]=i;
13             for(int j=i+i;j<=n;j+=i) st[j]=true;
14         }
15         
16     }
17 }
18 int main()
19 {
20     int n;
21     cin>>n;
22     get_prime(n);
23     cout<<cnt<<endl;
24     return 0;
25 }
复制代码

线性筛法

时间复杂度:O(n)

思路:

埃氏筛法中有些数是筛了多次的,有没有什么办法使他只筛一次呢?(比如:12,在2的倍数时筛了一次,在3的倍数里面也筛了一次)为此我们提出了线性筛法。

 

prime[]数组中的素数是递增的,当i能整除prime[j],那么i*prime[j+1]这个合数肯定被prime[j]乘以某个数筛掉。
因为i中含有prime[j],prime[j]比prime[j+1]小,即i=k*prime[j],那么i*prime[j+1]=(k*prime[j])*prime[j+1]=K*prime[j],
接下去的素数同理。所以不用筛下去了。
因此,在满足i%prime[j]==0这个条件之前以及第一次满足改条件时,
prime[j]必定是prime[j]*i的最小因子。

代码:

复制代码
 1 #include<iostream>
 2 using namespace std;
 3 const int N=1e6+10;
 4 int prime[N],cnt;
 5 bool st[N];
 6 void get_prime(int n)
 7 {
 8     for(int i=2;i<=n;i++)
 9     {
10         if(!st[i]) prime[cnt++]=i;
11         for(int j=0;prime[j]<=n/i;j++)
12         {
13             st[prime[j]*i]=true;
14             if(i%prime[j]==0) break;
15         }
16     }
17 }
18 int main()
19 {
20     int n;
21     cin>>n;
22     get_prime(n);
23     cout<<cnt<<endl;
24     return 0;
25 }
复制代码

 

posted @   Mrr-  阅读(241)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示