这里附上题目链接:P3912 素数个数。
~~手动分割~~
题目
思路解析
- 选用合适的素数筛法筛出区间[ 1,n ]的质数并计数,最后输出计数结果即可。
使用筛法需要开一个标记数组visit[ ]。因为题目有125.00MB的内存限制且此题数据范围较大,所以若将数组visit[ ]设为int型,将不能通过测试数据的最后两个点#9和#10。
在使用int型时,所耗内存100000000*4byte = 400000000 byte = 390625 kb = 381.46 Mb。
所以为了减小内存,可将数组visit[ ]定义为布尔型。一个bool变量只占一个byte。
1.欧拉筛法+布尔型变量标记(bool)
AC代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
int n,sum;//n为右界
int prime_permutation[1000000];
bool visit[99000000];//visit[i]=true说明i不是质数
int euler_sieve(int n)//n为右界
{
int i,j;
visit[0]=true;
visit[1]=true;//0和1不是素数
for(i=2;i<=n;i++)
{
if(!visit[i])//若i为素数
{
prime_permutation[sum]=i;
sum++;
}
for(j=0;j<sum&&(i*prime_permutation[j]<=n);j++)
{
visit[i*prime_permutation[j]]=true;
if(i%prime_permutation[j]==0)
{
break;
}
}
}
return 0;
}
int main()
{
//输入数据
scanf("%d",&n);
//筛选素数
euler_sieve(n);
//输出结果
printf("%d",sum);
return 0;
}
2.埃氏筛法+布尔型变量标记(bool)
AC代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
int n,sum;//n为右界,sum为数组prime_permutation的计数器
int prime_permutation[1000000];
bool visit[99000000];//visit[i]=true说明i不是质数
//埃氏筛法
int eratosthenes_sieve(int n)//n为右界
{
int i,j;
sum=0;
memset(visit,0,sizeof(visit));//先将标记数组清零
visit[0]=1;
visit[1]=1;//0和1不是素数
for(i=2;i<=n;i++)
{
if(!visit[i])//若i为质数
{
prime_permutation[sum]=i;//将i存入数组
sum++;
for(j=2*i;j<=n;j+=i)//质数i的整数倍一定不是质数
{
if(!visit[j])
{
visit[j]=1;
}
}
}
}
return 0;
}
int main()
{
//输入数据
scanf("%d",&n);
//筛选素数
eratosthenes_sieve(n);
//输出结果
printf("%d",sum);
return 0;
}