'); } '); } 参数传递 | Journey to paradise

参数传递


什么意思?

将规定范围内的数从大到小依次排列,从2开始依次筛去该数的倍数,因为素数的倍数一定不是素数,筛完后剩下的数即为素数。
eg:求1~100范围的素数,先去掉2的倍数,再去掉3的倍数,再去掉5的倍数…….,直到最后一个数,剩下的就是素数。

如何编程实现?

根据初始数据是从大到小依次排列的整数,可考虑设一个数组,数组下标代表需判断的数,数组的值代表该数是否为素数,
若为素数则数组项赋值为1,否则为0。用循环赋值下标为合数的数组项为0筛去合数,输出值为1的数组项的下标,即为所求素数。

可否优化?

可。某些数被重复判断筛选,降低运行效率。
eg:30=215=310=5*6,30作为2、3、5、6、15的倍数会被重复筛去。

怎样优化?

线性筛法:让每一个合数被它最小的质因数筛到。由于每个合数最小的质因数是唯一的,由不同的最小质因数筛到的合数也不同,这样就不会重复筛到同一个合数。

演示:eg 求1~12之间的素数
2 3 4 5 6 7 8 9 10 11 12
primes:()

从头到尾遍历,第一个数是2,未被划掉,把它放进质数表:
2 3 4 5 6 7 8 9 10 11 12
primes:(2,)

用2去乘质数表里的每个数,划掉它们:
2 3 4 5 6 7 8 9 10 11 12

下一个是3,加入质数表,划掉6、9:
2 3 4 5 6 7 8 9 10 11 12
primes:(2,3,)

下一个是4(注意这里划掉的数也要遍历,只是不加入质数表),先划掉8,但我们不划掉12,因为12 (12=26=34) 应该由它的最小质因数2筛掉,而不是3。
2 3 4 5 6 7 8 9 10 11 12
primes:(2,3,)

下一个是5,加入质数表,划掉10:
2 3 4 5 6 7 8 9 10 11 12
primes:(2,3,5)
……..

规律:对于一个数k,筛去k乘以primes数表里的数(从第一个开始)得到的合数,直到k可以整除primes中的某个数

按这样的步骤进行下去,可以筛掉所有的合数,并得到一张质数表。

代码(普通筛):

  #include <stdio.h>
  #define MAX 100
  int main(void)
  {
  int i, j;
  int isPrime[MAX + 1];
  for (i = 2; i < MAX + 1; i++)    //将所有数组项赋值为1,所有数默认为素数
  isPrime[i] = 1;

  for (j = 2; j * j < MAX; j++)    //将下标为合数的数组项赋值0,筛去合数
    for (i = j; i < MAX + 1; i++)
      if (!(i % j))
        isPrime[i] = 0;

  for (i = 2; i < MAX + 1; i++)   //输出值为1的数组项下标,即为素数
    if (isPrime[i] == 1)
      printf("%d ", i);

  return 0;
  }

优化后(线性筛):

  #include <stdio.h>
  #define MAX 100
  int main(void)
  {
    int i, j, count = 0;
    int isPrime[MAX + 1], primes[MAX + 1]={0};
    for (i = 0; i < MAX + 1; i++) //将所有isPrime数组项赋值为1,默认所有数均为素数
      isPrime[i] = 1;
    for (i = 2; i < MAX + 1;i++) 
       {

         if(isPrime[i])        //将确认的素数存入primes数组
           primes[count++] = i;
         for (j = 0; j <= count && primes[j] * i <= MAX;j++)   //用线性筛法筛去合数
           {
             isPrime[i * primes[j]] = 0;
             if(i%primes[j]==0)
               break;
           }
       }
       for (i = 0; i <count;i++)             //输出数组primes,即输出所求的所有素数
         printf("%d ", primes[i]);

         return 0;
  }

线性(欧拉)筛原理论证参考


文章作者: 涂爽
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 涂爽 !
评论
  目录