线性筛法求素数
题目
给定一个正整数 n,请你求出 1∼n 中质数的个数。
输入格式
共一行,包含整数 n。
输出格式
共一行,包含一个整数,表示 1∼n中质数的个数。
数据范围
1≤n≤1e6
输入样例:
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 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了