素数的求解是数论题目中频繁遇到的问题,下面介绍几种求 n 以内的素数的算法

全局定义:

1 const int n = ?;        //n范围
2 const int m = ?;        //素数个数
3 bool vis[n];            //标记数组
4 int prime[m];            //存素数
5         

 

1、较为高效的筛法

  思想:从 2 开始,即标记数组为0(或为1),当标记数组为 0(或1) 时,该数为素数,把素数的倍数筛掉。此算法缺陷在于会重复筛选有不同素数因子的合数(比如说6,被2筛一次,又被3筛一次)

代码:

复制代码
 1 void getprime1()            //因为标记的时候会出现大量重复
 2 {
 3     memset(vis, 0, sizeof(vis));
 4     int k = 0;
 5     for(int i = 2; i < n; ++i)
 6         if(!vis[i])
 7         {
 8             prime[k++] = i;
 9             for(int j = i*i; j < n; j += i)
10                 vis[j] = 1;
11         }
12 }
复制代码

2、线性筛法

  线性筛法就是为了避免重复筛掉同一个合数。思想是:从2 开始遍历,遇到素数就记录下来,当 i 遍历到为前面已经存储的素数的倍数的时候,就跳出循环,这样不仅可以筛选出所有素数,而且避免了重复。

代码:

复制代码
 1 void getprime2()        //线性筛法
 2 {
 3     memset(vis, 0, sizeof(vis));
 4     int k = 0;
 5     for(int i = 2; i < n; ++i)
 6     {
 7         if(!vis[i])    prime[k++] = i;
 8         for(int j = 0; (j<k && i*prime[j]<n ); ++j)
 9         {
10             vis[i*prime[j]] = 1;
11             if(i%prime[j] == 0)    break;
12         }
13     }
14 }
复制代码

优化:

优化原理:除了2以外,所有素数都是奇数,所以排除2以后,i 就可以不管偶数了,值得注意的是,排除 2 之后,prime[4] 要清除标记。

代码:

复制代码
 1 void getprime3()    //线性筛法改良
 2 {
 3     memset(vis, 0, sizeof(vis));
 4     int  k = 1;
 5     prime[0] = 2, vis[4] = 1;
 6     for(int i = 3; i < n; i += 2)
 7     {
 8         if(!vis[i])    prime[k++] = i;
 9         for(int j = 0; (j<k && i*prime[j]<n); ++j)
10         {
11             vis[i*prime[j]] = 1;
12             if(i%prime[j] == 0)    break;
13         }
14     }
15 }
复制代码

 

 posted on 2013-09-18 16:42  ∑求和  阅读(164)  评论(0)    收藏  举报