zoukankan      html  css  js  c++  java
  • 【算法氵】筛法

    埃拉托斯特尼筛法:

    质朴的算法:

      确认质数:从2开始,从小到大找第一个未被筛去的数

      筛去合数:确认是质数之后,筛去质数的所有倍数

    因此程序大概就是

    埃拉托斯特尼筛

    记得小学课本学“素数”的时候就有类似的图:

      一张10*10的数表,从2开始,从小到大找第一个未被划斜杠的数,之后将其的倍数全部杠掉

     (缺图)

    很快就会发现,2筛去了一半的数,而之后的偶数几乎都被筛去了很多次(类似于鞭尸。。),也就是说,花费了很多无用的时间来筛去已经被筛过的数

    于是我们很容易就会想到这样的优化:当当前”筛子“不为2时,每次隔1个数筛一个

    以此类推,隔2个隔3个……

    于是最终就可以迭代到欧拉筛法:

    欧拉筛法:

      “思想是 使每个数只被其最小质因数所筛去 ”

    讲起来简单,但却不好实现

    一种实现的办法是:

      之前的埃筛法中,只有素数可以当筛子,因为判定素数和筛除操作是一起执行的

      我们知道,所谓合数,也就是可以表达成素数幂之积

      如:6174=2*3*3*7*7*7

      按照欧拉筛法的思想,应该使得6174被2筛去,但是如果合数也可以做筛子:

        那么可以让6174被3087筛去

        3087被1029筛去

        1029被343筛去

        343被49筛去

        49被7筛去

        7没有被比它小的数所筛去,可以确定7是素数

      也就是说,如果每个素数筛去 该素数与 不大于它的素数 之积,合数筛去 该合数与 不大于它最小质因子 的素数 之积,就可以不重复不遗漏(类似于数学归纳法)

    举例:

      2做筛子,筛去4

      3做筛子,筛去6,9

      4做筛子,筛去8

      5做筛子,筛去10,15,25

      6做筛子,筛去12

      7做筛子,筛去14,21,35,49

      8做筛子,筛去16

      9做筛子,筛去18,27

      10做筛子,筛去20

      11做筛子,筛去22,33,55,77,121

      12做筛子,筛去24

      13做筛子,筛去26,39,65,91,143,169

      14做筛子,筛去28

      15做筛子,筛去30,45

      16做筛子,筛去32

      17做筛子,筛去34,51,85,119,187,221,289

    ……大概就是这样子

    因此:

      确认质数:从2开始,从小到大找第一个未被筛去的数

      筛去合数:每个数都筛去 它与 不大于它的素数 之积,如果这个数是合数,则发现其第一个因子的时候停止筛除操作

     代码如下

     1 for(int i=2; i<=MAX; ++i) {
     2     if(!number[i])
     3         prime[++ctprime]=i;
     4     else
     5         for(int ii=1; i*prime[ii]<=MAX && ii<=ctprime; ++ii) {
     6             number[i*prime[ii]]=true;
     7             if(i%prime[ii]==0)
     8                 break;
     9         }
    10 }
    11 // bool number[MAX]= {1,1,0};//0为素数,MAX为数据规模
    12 // int prime[]= {0,2};//这个数组可以比MAX小很多
    13 // int ctprime;//初始值为0
    线性筛
     1 for(int i=2; i<=MAX; ++i) {
     2         if(!number[i]) {//优化:素数一定可以筛到它的平方,减少判断
     3             prime[++ctprime]=i;
     4             for(int ii=1; ii<=ctprime && i*prime[ii]<=MAX; ++ii)
     5                 number[i*prime[ii]]=true;
     6         } else
     7             for(int ii=1; i*prime[ii]<=MAX && ii<=ctprime; ++ii){
     8                 number[i*prime[ii]]=true;
     9                 if(i%prime[ii]==0)
    10                     break;
    11             }
    12     }
    稍微优化一下的版本

    OVER

      

      

  • 相关阅读:
    hadoop-0.20-集群搭建___实体机通过SSH访问基于VM安装的Linux
    Kettle的集群排序 2——(基于Windows)
    在使用Kettle的集群排序中 Carte的设定——(基于Windows)
    POJ3083
    本地tomcat访问mysql数据库
    正则表达式——(一)
    图论——读书笔记 (深度优先搜索)
    c# 反射+Attribute 实现获取Description的两种做法
    排序方法的总结
    c# 初识Actor Model
  • 原文地址:https://www.cnblogs.com/MirrozSigmaMax/p/13917140.html
Copyright © 2011-2022 走看看