原题链接如下:
868. 筛质数 - AcWing题库
埃氏筛法
#include<iostream>
using namespace std;
const int N = 1e6+10;
int prime[N],cnt;//prime是存储所有质数的数字,cnt是prime数组的下标,因此也能反映出质数的个数
bool st[N];//标记一个数是否为质数 true是合数 false是质数
int n;
void get_primes(int n)
{
for(int i = 2;i<=n;i++)
{
if(st[i])continue;//是合数 就跳过 不加到prime数组中
//是质数 就走到了这一步不会被上面continue掉
prime[cnt++] = i;
//把这个质数的倍数 全部筛选掉 因为他们肯定不再是质数了 标记成合数
for(int j = i+i;j<=n;j+=i)
{
st[j] = true;//设置成合数
}
}
}
int main()
{
cin>>n;
get_primes(n);
cout<<cnt<<endl;
return 0;
}
线性筛法(时间复杂度O(n))
这个方法有很大的学问,值得好好钻研,而且后面也可以采用这个方法求解欧拉函数值
y总示范代码:
题解:
AcWing 868. 对于——筛质数——三种方法的解释 - AcWing
#include<iostream>
using namespace std;
const int N = 1e6+10;
int prime[N],cnt;
bool st[N];//标记数是否为质数 true是合数 false是质数
int n;
void get_primes(int n)
{
//这次我们采用筛质数法
//外层从2~n迭代,因为这毕竟算的是1~n中质数的个数,而不是某个数是不是质数的判定
for(int i = 2;i<=n;i++)
{
if(!st[i])prime[cnt++] = i;//把所有的质数加到prime数组当中
for(int j = 0;prime[j]*i<=n;j++)
{
st[prime[j]*i] = true;//由于每个合数都存在最小质因子,所以我们用最小质因子去筛选合数
//1)当i%primes[j]!=0时,说明此时遍历到的primes[j]不是i的质因子,那么只可能是此时的primes[j]<i的
//最小质因子,又由于primes[j]*i的最小质因子,只可能是min{primes[j],i的最小质因子}
//所以primes[j]*i的最小质因子就是primes[j];
//2)当有i%primes[j]==0时,说明i的最小质因子是primes[j],因此primes[j]*i的最小质因子也就应该是
//prime[j],之后接着用st[primes[j+1]*i]=true去筛合数时,就不是用最小质因子去更新了,因为i有最小
//质因子primes[j]<primes[j+1],此时的primes[j+1]不是primes[j+1]*i的最小质因子,此时就应该
//退出循环,避免之后重复进行筛选.
if(i%prime[j] == 0)break;
}
}
}
int main()
{
cin>>n;
get_primes(n);
cout<<cnt<<endl;
return 0;
}