• 素数之筛法


    筛法

    筛素数的常用手段:

    1、Eratosthenes 筛法

    复杂度:O(n log (log n))

    从小到大找到一个素数,筛掉所有它的倍数。

    代码:

     1 void Prim(int n)
     2 {
     3     //Eratosthenes筛选法
     4     memset(check,false,sizeof(check));
     5     int tot = 0;
     6     for(int i = 2;i  <= n;i ++)
     7         if(!check[i])
     8         {
     9             prim[tot++] = i;
    10             for(int j = 2*i;j <= n;j += i)
    11                 check[j] = true;
    12         }
    13 }
    View Code

    2、Euler 筛法(重要!!!)

    复杂度:O(n)

    鉴于前者算法的优化,因为上面的算法一个非素数可能会被多个质因数筛多次,浪费了,所以优化掉这个,只用一个数最小的质因数排除(筛掉)这个数字。

     1 void Euler_prim(int n)
     2 {
     3     //欧拉筛选法     避免上面筛选法中的重复筛选
     4     memset(check,false,sizeof(check));
     5     int tot = 0;
     6     for(int i = 2;i <= n;i ++)
     7     {
     8         if(!check[i]) prim[tot ++] = i;
     9         for(int j = 0;j < tot;j ++)    //遍历已经找到的素数
    10         {
    11             if(i * prim[j] > n) break;   //后面相乘已经超出 n 的范围,没有查找的必要了
    12             check[i * prim[j]] = true;    //表示这个数字不是素数
    13             if(i % prim[j] == 0) break;   
    14         }
    15     }
    16 }

    重点解释下 if (i%prim[j]==0) break 这句话:

    因为prim[j]是i的最小质因数了,如果这时候继续筛下去,下一个数为i*prim[j+1],因为 i=prim[j]*k,对于这个数来说最小质因数是prim[j],而这时却要用prim[j+1]来筛,则与我们要达到的要求、效果违背,这个数肯定会在以后被Prim[j]筛掉,所以直接break就行了,后面的肯定也会被prim[j]筛掉。

    (不知道这样理解对不对。。。)

    fighting fighting fighting !!!

  • 相关阅读:
    「2019纪中集训Day20」解题报告
    PHP基础入门
    javascript
    正则表达式
    DOM 节点
    对象
    字符串
    函数
    for循环
    jQuery
  • 原文地址:https://www.cnblogs.com/Frank-King/p/9928437.html
Copyright © 2020-2023  润新知