#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
bool visit[10100000];//将是素数的数标记为1(注:从0开始,0,1也被标记了)
int prime[1000000];//将素数依次存入(从下标1开始存)
int init_prime(int number)
{
memset(visit, true, sizeof(visit));
int num = 0;
for (int i = 2; i <= number; ++i)
{
if (visit[i] == true)
{
num++;//素数个数
prime[num] = i;
}
for (int j = 1; ((j <= num) && (i * prime[j] <= number)); ++j)
{
visit[i * prime[j]] = false;
if (i % prime[j] == 0){
break;
}
}
}
return num;
}
int main()
{
int number;
scanf("%d",&number);
printf("%d\n",init_prime(number));//不大于number的数是素数的个数
}
原理:
1. 任何一个合数都可以表示成一个质数和一个数的乘积2. 假设A是一个合数,且A = x * y,这里x也是一个合数,那么有:
即一个合数(x)与一个质数(y)的乘积可以表示成一个更大的合数(Z)与一个更小的质数(a)的乘积
这也是理解代码中 if(i%primes[j] == 0)break;的关键
例如: 如果i = 8; 那么由于i%2 == 0;因此对于i=8就只需要检查primes[1]即可,因为对于大于primes[1]的质数,像3,有:
也就是说24(8*3=24)并不需要在8时检查,在12时才检查 ,因此break掉,不用重复判断.