线性筛法求素数
题目
给定一个正整数 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 }

浙公网安备 33010602011771号