zoukankan      html  css  js  c++  java
  • 素数的生成筛选法

    基础思路

    """
    一个简单的筛素数的过程:n=30。
    1 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 30
    
    第 1 步过后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)算法结束
    """
    
    def imouren_primes(n):
        maps = n*[True]
        maps[0] = False
        maxs = int(n**0.5+1)
        for i in xrange(1,maxs):
            if maps[i]:
                maps[i::i+1] = len(maps[i::i+1])*(False,)
                maps[i] = True
        res = [i+1 for i, v in enumerate(maps) if v]
        return res
    

    继续优化

    """
    则由于只存3 5 7 9 11 13 15 17 19 21 23 25 27 29,只需要14个单元
    第 1 步 把14个单元赋为true (每个单元代表的数是2*i+3,如第0单元代表3,第1单元代表5...)
    第 2 步开始:
         i=0;  由于prime[0]=true, 把 [3], [6], [9], [12]标为false.
         i=1;  由于prime[1]=true, 把 [6], [11]标为false
         i=2  2*i+3>sqrt(30)算法结束
    这样优化以后总共只走6个单位时间
    """
    def imouren_primes2(n):
        maps = (n-1)//2*[True]
        maxs = int(n**0.5+1)
        for i in xrange(len(maps)):
            if 2*i+3 > maxs:
                break
            if maps[i]:
                maps[i::2*i+3] = len(maps[i::2*i+3])*(False,)
                maps[i] = True
        res = [(i+1)*2+1 for i, v in enumerate(maps) if v]
        res.insert(0,2)
        return res
    

    再次优化

    """
    比如我们看到的,i=0与i=1时都标了[6],这个就是重复的计算
    我们可以发现一个规律,那就是3(即i=0)是从下标为[3]的开始筛的,5(即i=1)是从下标为[11]开始筛的(因为[6]
    已经被3筛过了)。然后如果n很大的话,继续筛。7(i=2)本来应该从下标为[9]开始筛,但是由于[9]被筛过了,而
    [16]也已经被5(i=1)筛过了。于是7(i=2)从[23](就是2*23+3=49)开始筛。
    于是外围循环为i时,内存循环的筛法是从 i+(2*i+3)*(i+1)即i*(2*i+6)+3开始筛的。
    """
    def imouren_primes3(n):
        maps = (n-1)//2*[True]
        maxs = int(n**0.5+1)
        for i in xrange(len(maps)):
            if 2*i+3 > maxs:
                break
            if maps[i]:
                maps[i*(2*i+6)+3::2*i+3] = len(maps[i*(2*i+6)+3::2*i+3])*(False,)
                maps[i] = True
        res = [(i+1)*2+1 for i, v in enumerate(maps) if v]
        res.insert(0,2)
        return res
    
  • 相关阅读:
    201920201学期 20192410《网络空间安全专业导论》第一周学习总结
    201920201学期 20192410《网络空间安全专业导论》第二周学习总结
    Oracle trunc()函数的用法
    20130528
    让ListBox控件支持拖动
    幸福是什么
    实例解析C++/CLI程序进程之间的通讯
    Boost源码剖析之:容器赋值assign
    VC++ MFC 多线程及线程同步
    MFC下窗口分割和文字输出的实现
  • 原文地址:https://www.cnblogs.com/imouren/p/2859054.html
Copyright © 2011-2022 走看看