原理:任何一个合数都可以表示成一个质数和一个数的乘积
假设A是一个合数,且A = x * y,这里x也是一个合数,那么有:
A = x * y; (假设y是质数,x合数)
x = a * b; (假设a是质数,且a < x——>>a<y)
-> A = a b y = a Z (Z = b y)
即一个合数(x)与一个质数(y)的乘积可以表示成一个更大的合数(Z)与一个更小的质数(a)的乘积,那样我们到每一个数,都处理一次,这样处理的次数是很少的,因此可以在线性时间内得到解。
仍然按上面的例子模拟(这里0为是素数,1为非素数,p为记录的素数表):
初始:
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
p(empty)
然后到2的位置,把2放入素数表,做当前范围内可以筛掉的处理(具体是怎样的看代码叭):
1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
p 2 到3,把3放入素数表,继续处理
1 0 0 1 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0
p 2 3 然后到了4,它不是个素数,也处理一下
1 0 0 1 0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0
p 2 3 .......
然后一直搞下去,最后也能得到完整的素数表,这样虽然看起来复杂一些,但是实际上我们发现对于每个数的处理几乎是O(1)的。
void get_list(){
for(int i=2;i<=maxn;i++){
if(!is_not_pr[i]) prime[++tot]=i;
for(int j=1;j<=tot&&i*prime[j]<=maxn;j++){
is_not_pr[i*prime[j]]=1;//合数标为1,同时,prime[j]是合数i*prime[j]的最小素因子
if(i%prime[j]==0) break;//即比一个合数大的质数和该合数的乘积可用一个更大的合数和比其小的质数相乘得到
}
}
}

5万+

被折叠的 条评论
为什么被折叠?



