算法——筛法求素数

来源:互联网 发布:linux 显示进程 命令 编辑:程序博客网 时间:2024/05/03 18:35

筛法素数打表

很早就已经学过筛法的代码了。当时就是强行给记下代码了。现在结合一下思想,把最优化的办法找出来。

筛法求素数不同于我们之前在C语言书上说的那两种方法。第一种是在[2,n)上不被整除。第二种是在[2,sqrt(n)]不被整除。这两种在思想和实现上是没有问题的。但是会耗时很多。以至于,在各大OJ上的素数题中,总是会time limited。

筛法求素数的思想也很简单。一个数的倍数都不是素数。

首先我们开一个数组。
比如 2,那么2的倍数都不是素数。在第一次循环中我们就剔除所有2的倍数。
后面依次类推。
因为1不是素数。我们一般从2开始。
以下面数字举例
2 3 4 5 6 7 8 9 10
第一次
2 3 5 7 9
第二次
2 3 5 7
这样就得到我们想要的素数了。
以此思想为辅助,我写出以下代码、

for(int i=2;i<-N;i++)    Prime[i]=1;for(int i=2;i<=sqrt(N);i++){        if(Prime[i]==1){            for(int j=i*2;j<N;j+=i){                    Prime[j]=0;            }        }    }

这个基本是符合上面所述思想的。Prime[]是一个全局数组。N是宏定义中的常量。这里我设置的是100.
最后的打印就是,当Prime[i]==1时,就存i进去。

然后在师父的指导下,有了更进一步优化的办法。
比如 sqrt(N)我们可以用一个变量表示。因为放在循环中,每次都要算一遍,这也是耗时的。还有改进的地方就是,既然数组是全局变量,默认给定值是0.。我们可以把非素数置1 这样又可以省去一个初始化循环。j也可以从i*i开始,这样判断速度会快一些。

改进后的代码如下

    for(int i=2;i<=m;i++){        if(Prime[i]==0){            for(int j=i*i;j<N;j+=i){                    Prime[j]=1;            }        }    }    for(int i=2;i<N;i++){        if(Prime[i]==0)            Prime[count++]=i;    }

当然这个count完全可以用memset函数代替。。但是我不太会用,我觉得还是设置一个变量count比较能让我懂。
最后也方便我自己输出。

以上纯属个人理解。。
错了欢迎指出。。。。
QWQ总之也是很有用的东西呢。

0 0
原创粉丝点击