[数值问题]素数筛选
内存限制:128 MB时间限制:1.000 S
题目描述
输入一正整数n(2<=n<=5*10^6),按顺序输出2到n范围内的所有素数。
输入
输入共一行一个数,表示n的值。
输出
输出若干行,每行5个素数,用空格隔开。
样例输入
20
样例输出
2 3 5 7 11
13 17 19
素数在很多应用领域有很重要的用途,寻找一个高效的算法十分重要。例如,找出10000以内的素数可能仅仅是为某个程序做的准备工作,为提高程序的效率,希望在尽可能短的时间内完成。下面介绍一个经典算法——筛选法求素数。
主要思想是以空间换时间,是很常用的一种提高算法效率的方法。这是一种思想,不是一种算法。这种思想的主要应用有以下两种:
第一种是将之前计算的结果保存起来,方便当前计算之用,从而降低计算量。这种思想的典型体现就是动态规划算法,从求解规模较小的子问题开始,逐步递推求解规模更大的子问题,每次计算都将得到的最优结果保存起来,在后面的计算中,利用前面的计算结果求得当前的最优值,然后再保存起来,如此递推下去。
所谓筛选法是指从小到大筛去一个已知素数的所有倍数。以筛选法求10000以内的素数为例,根据素数2可筛去4、6、8、…、9998、10000等数,然后根据索数3可筛去9.6.
12.15,…,9999等数,由于4已被筛去了,下一个用于筛选的素数是5…依此类推,最后剩余的就是10000以内的素数。
具体实现代码如下:
#include<stdio.h>
#define N 5000000//根据题意开一个数组
#include<math.h>
int a[N+1];//全局变量数组
void prime(int n)
{
int m=0,i,j;
for(i=0;i<n;i++)
a[i]=1;//给所有数赋值为1
a[0]=a[1]=0;//0和1不是素数
m=(int)sqrt(n);
for(i=2;i<=m;i++)//从二开始依次筛选2,3....的倍数
{
if(a[i]==1)//筛选过的就不需要进入循环了,如2的倍数有4,4已经被筛选了即a[4]==0不进入循环
{
for(j=2*i;j<n;j=j+i)
{
a[j]=0;//将不是素数的数赋值为0
}
}
}
}
int main(void)
{
int n,i,b=0;
scanf("%d",&n);
prime(n);//使用函数筛选
for(i=1;i<=n;i++)
{
if(a[i]==1)//输出筛选后剩余的素数
{
printf("%d ",i);
b++;
if(b==5)//五个数一行
{
printf("\n");
b=0;//用完初始化
}
}
}
return 0;
}