#define _CRT_SECURE_NO_WARNINGS
/*求小于等于n的素数的个数*/
#include<stdio.h>
#include<string.h>
using namespace std;
const int maxn = 1e6 + 5;
int prime[maxn], cnt;//存素数
bool vis[maxn];//保证不做素数的倍数
void getprime(int n)
{
cnt = 0;
for (int i = 2; i <= n; i++)//让每个素数都乘上大于2的自然数
{
if (!vis[i])//不是目前找到的素数的倍数
prime[++cnt] = i;//找到素数
for (int j = 1; j < cnt && i * prime[j] <= n; j++)//所得素数小于i, 合数=i * prime[j]属于n不能大于n
{
vis[i * prime[j]] = true;//找到的素数的倍数不访问
if (i % prime[j] == 0) break;//关键!!!! 比如12=2*6=3*4,如果没有这一步的话就会出现左面的2种情况,
//导致数据重复处理,因为3*4=3*2*2,所以3根本不是最小质因子,为了让这种情况消失,故采用i % prime[j]==0;然而i % prime[j]是表示合数=素数*一个数
//若这个数除以素数等于0说明这个数是素数的倍数,故还可以分解如上面的3*4=3*2*2,就是判断素数*一个数时这个素数是不是最小质因数故采用这种方法剔除,
//这种方法的原理对于 i%prime[j] == 0 就break的解释 :当 i是prime[j]的倍数时,i = kprime[j],如果继续运算 j+1,i * prime[j+1] = prime[j] * k prime[j+1],
//对于 i%prime[j] == 0 就break的解释 :当 i是prime[j]的倍数时,i = kprime[j],如果继续运算 j+1,i * prime[j+1] = prime[j] * k prime[j+1],而我们知道素数是递增的,
//故这里prime[j]是最小的素因子,当i = k * prime[j+1]时会重复,而不是所谓的prime[j+1]所以才跳出循环。
}
}
}
int main()
{
int n;
scanf_s("%d", &n);
getprime(n);
printf("%d\n", cnt);
return 0;
}
欧拉筛(代码详解)
最新推荐文章于 2024-07-18 21:05:10 发布