素数筛选法
素数筛选法一直是数论中的重点,你找到的规律越多你的筛选就越快。
先让我们 看一个算法:
#include<stdio.h>
#include<math.h>
#define MAX_P 500
int nList[MAX_P] = {0};
void Calc()
{
int n,p,t,sq=(int)sqrt(MAX_P*2+1);
for (n=3;n<=sq;n+=2)
{
if (nList[n>>1]) continue;
for (t=n*n;t<=MAX_P<<1;t+=n<<1) //筛选循环
nList[t>>1] = 1;
}
printf("%5d", 2);
for (n=t=1;t<MAX_P;++t)
{
if (nList[t]) continue;
printf("%5d", (t<<1)+1);
if (++n==10)
{
printf("\n");
n=0;
}
}
}
int main(void)
{
Calc();
getchar();
return 0;
}
该算法是一种优化的算法,它不仅时间上优化而且在空间上优化了;为什么可以只要开一半的素组,因为素数只可能是奇数(除开2)那么我们可以好好利用该空间;
我们知道奇数除以2是对其取整数了,例如3/2=1,5/2=2......(2*n+1)/2=n;所以我们只要开一半的数组;
for (n=3;n<=sq;n+=2)
{
if (nList[n>>1]) continue;
for (t=n*n;t<=MAX_P<<1;t+=n<<1) //筛选循环
nList[t>>1] = 1;
}
我们都知道对素数的筛选只要到sqrt()就可以了,这里就不证明了,第一个循环是对所有奇数进行筛选,第二个循环是对素数的倍数进行剔除,为什么每次是2*n了,因为n*n是奇数而素数一定是奇数,如果是t+=n;由于t是奇数n也是奇数那么t+=n就是偶数,而t+=2*n就是奇数并且是n的倍数(因为一倍不可能,已证);
如果是它的倍数就标记。