埃拉托色尼筛中函数的反演

问题描述 投票:0回答:1

我认为这在技术上是轮分解。我正在尝试重新压缩我的程序对埃拉托斯特尼筛法的表示,它只包含可能是素数的数字索引。

一些背景:

最基本的轮子是[2]:跟踪2作为第一个素数,并且筛子仅包含奇数索引。 (50%))

下一个轮子是[2 3]:记录2和3作为第一个素数,筛子仅包含2*3=6之间的间隙(即1和5)。索引的形式为 6k+1 和 6k+5。 (33%)

下一个轮子是[2 3 5]:跟踪2、3和5作为第一个素数,筛子只需要8位来表示大小为30的间隔。(27%)

当清除数字的倍数位时,我使用此循环找到这些倍数:

def multiplesIndices (self, i):
    for gap in self.gaps[1:]:
        ret = i * (self.product * 0 + gap)
        if ret > len (self): break
            yield ret
    for k in xrange (1, len (self) / i / self.product + 1):
        for gap in self.gaps:
            ret = i * (self.product * k + gap)
            if ret > len (self): break
            yield ret

问题在于设置车轮所需的时间,以及压缩比的收益递减。好吧,改变到不同的车轮尺寸需要大量的重新计算。另外,通过改变轮子尺寸,我认为我可以影响渐近复杂度。

所以我提出的解决方案是使用小轮子来初始化较大的轮子: [2 3] (6/2) 获取 [2 3 5] (30/8) 轮中的间隙 [2 3 5] 获取 [2 3 5 7] (210/48) 轮中的间隙

我需要帮助的地方是将已经计算的小筛子映射到要计算的大筛子,这样我就可以避免重新筛选从1开始的所有内容。获取前30个素数,用它们找到接下来的210-30个素数,用它们来找到接下来的 480-210 个素数。

更具体地说,我需要帮助反转此函数(或正确实现 invIndexOf()):

def indexOf (self, n):
    if not self.isValidIndex (n): raise Exception ()
    ret = n / self.product * len (self.gaps) + self.gaps.index (n % self.product)
    assert n in self.invIndexOf (ret)
    return ret

而且,自从我计算出任何事物的渐近复杂性以来,已经有几年了。我很确定这是一种改进,尽管不是很大。

sieve-of-eratosthenes inverse wheel-factorization
1个回答
© www.soinside.com 2019 - 2024. All rights reserved.