• 数论学习日记一—超快的素数筛选法(改进)


    素数筛选法:

    最近发现了一个用bool数组去判断素数的方法,很强大,速度非常之快,方法是从大佬博客:https://www.cnblogs.com/wpnan/p/4073852.html 截下来的,可以看去看一下。

        素数筛法是这样的:
        1.开一个大的bool型数组prime[],大小就是n+1就可以了.先把所有的下标为奇数的标为true,下标为偶数的标为false.
        2.然后:
          for( i=3; i<=sqrt(n); i+=2 )
          {   if(prime)
              for( j=i+i; j<=n; j+=i ) prime[j]=false;
          }
        3.最后输出bool数组中的值为true的单元的下标,就是所求的n以内的素数了。
        原理很简单,就是当i是质(素)数的时候,i的所有的倍数必然是合数。如果i已经被判断不是质数了,那么再找到i后面的质数来把这个质
    数的倍数筛掉。
        一个简单的筛素数的过程:n=301 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 301 步过后2 4 ... 28 30这15个单元被标成false,其余为true。
        第 2 步开始:
         i=3;  由于prime[3]=true, 把prime[6], [9], [12], [15], [18], [21], [24], [27], [30]标为false.
         i=4;  由于prime[4]=false,不在继续筛法步骤。
         i=5;  由于prime[5]=true, 把prime[10],[15],[20],[25],[30]标为false.
         i=6>sqrt(30)算法结束。
        第 3 步把prime[]值为true的下标输出来:
         for(i=2; i<=30; i++)
         if(prime) printf("%d ",i);
        结果是 2 3 5 7 11 13 17 19 23 29

    内容非常清晰明了,利用bool数组去筛选也确实是普通判断素数方法的好几倍,不过观察了一下大佬的代码发现方法还可以有进一步改进,我先将大佬的原代码发上来:

     1 //用了筛法的方法:
     2 #include<stdio.h>
     3 #include<math.h>
     4 #define N 10000001
     5 bool prime[N];
     6 int main()
     7 {
     8    int i, j;
     9    for(i=2; i<N; i++)
    10   if(i%2) prime=false;
    11   else prime=true;
    12    for(i=3; i<=sqrt(N); i+=2)
    13    {   if(prime)
    14        for(j=i+i; j<N; j+=i)
    15 
    16             prime=false;
    17    }
    18    for(i=2; i<100; i++)//由于输出将占用太多io时间,所以只输出2-100内的素数。可以把100改为N
    19     if( prime )
    20 
    21          printf("%d ",i);
    22    return 0;
    23 }

    可以优化的有两个地方,第一是一开始就给bool数组分配了很大的不一定需要的空间,这样有时候是很占内存的,第二就是判断素数的时候可以用位运算去判断,位运算判断奇偶数的速度大概是i%2的4倍左右,改进后的代码如下:

     1 #include<iostream>
     2 #include<math.h>
     3 #include<conio.h>
     4 #include<malloc.h>
     5 using namespace std;
     6 
     7 int main(int argc, const char * argv[])
     8 {
     9     int n;
    10     cin >> n;
    11     bool * num = (bool *)malloc((n + 1) * sizeof(bool));//如果需要判断n以内的素数,就直接分配n+1的空间,这样就可以节省很多内存。
    12     for (int i = 2; i <= n ; i++)
    13     {
    14         if (((1&i)==0) && (i!= 2) ) num[i] = false;//利用位运算判断奇偶
    15         else num[i] = true;
    16     }
    17     for (int i = 3; i <= sqrt(n); i += 2)
    18     {
    19         if (num[i])
    20             for (int j = i + i; j <= n; j += i)
    21                 num[j] = false;
    22     }
    23     for (int i = 2; i <= n; i++)
    24         if (num[i] == true )cout << i << endl;
    25     _getch();//不是在vs里面运行的不需要加这一行
    26     return 0;
    27 }

    大佬的思路是真的强,没看之前还真不知道可以利用bool数组去加快判断速度,还是有很多地方可以向大佬学习的!

  • 相关阅读:
    suse12安装详解
    Centos7上部署openstack mitaka配置详解(将疑难点都进行划分)
    菜鸟帮你跳过openstack配置过程中的坑[文末新添加福利]
    openstack中dashboard页面RuntimeError: Unable to create a new session key. It is likely that the cache is unavailable.
    Multiple network matches found for name 'selfservice', use an ID to be more specific.报错
    查看 SELinux状态及关闭SELinux
    SELinux深入理解
    IP地址、子网掩码、网络号、主机号、网络地址、主机地址
    Oracle job procedure 存储过程定时任务
    POI文件导出至EXCEL,并弹出下载框
  • 原文地址:https://www.cnblogs.com/xiangqi/p/11102420.html
Copyright © 2020-2023  润新知