4

这是一种基于从序列中的一个数字到下一个数字的间隔来生成汉明数序列(又名常规数字5-平滑数字)的稍微不同的方法。这是所述间隔的示例图:

在此处输入图像描述

因此,将一个数字与下一个数字分开的离散区间数量相对有限,并且随着 H 的增加,区间变得更小。人们经常注意到,汉明数随着大小的增加而变得越来越稀疏,从绝对意义上讲,它们确实如此,但在另一种意义上(按比例),它们变得更接近。

基本上,随着 H 的上升,2^i*3^j*5^k 的机会更大,其中 i,j,k 是正整数或负整数,导致小数接近 1.0。

事实证明,只有 119 个区间(i、j、k 三元组)的表涵盖了高达约 10^10000 的汉明数。这大约是前 1.59 万亿个海明数。这样一个表(C头文件),按区间大小从小到大排序,就在这里。给定一个汉明数,要找到下一个,只需要找到表中的第一个条目,其中乘法(各个指数相加)将产生对 i、j 和 k 具有正幂的结果。

例如,第 100 万个海明数是 2^55*3^47*5^64,大约是 5.1931278e83。之后的下一个汉明数是 2^38*3^109*5^29 或大约 5.1938179e83。第一个适当的表条目是:

{-17,62,-35}, // 1.000132901540844

因此,虽然这些数字相隔约 7e79,但它们的比率为 1.000132901540844。要找到下一个数字,在最坏的情况下只需要尝试最多 119 个条目,只涉及加法和比较(没有乘法)。此外,每个条目只有 3 个短整数的表需要不到 1kb 的内存。该算法基本上在内存中为 O(1),在时间上为 O(n),其中 n 是序列的长度。

一种加快速度的方法是,不是每次都从第 0 个索引开始搜索表,而是将表条目列表限制为仅搜索那些凭经验已知会在给定范围内成功的条目(n < 1.59 e12)。这些列表在 succtab[] 结构的上述头文件中给出,例如:

{11,{47,55,58,65,66,68,70,72,73,75,76}},

因此,凭经验发现该特定索引后仅跟随列出的 11 个不同索引,因此仅搜索这些索引。

这样做可以将算法速度提高 4 倍左右,在此处实现(C 代码)以及上面的头文件。这是 i7-2600 3.4GHz 机器上的执行时间图:

在此处输入图像描述

我相信这与最先进的技术相比是有利的——是这样吗?

汉明问题有时会简化为仅找到第 n 个汉明数而不生成所有中间值。将上述技术应用于一个众所周知的方案,即仅在所需范围附近的一个频带中枚举汉明数,就可以得到这个执行时间图: 在此处输入图像描述

因此,找到第 1.59 万亿个海明数只需要不到 2 秒的时间。C 代码在这里。至少在给定的范围内,这是否也与最先进的技术相媲美?

编辑:n(1.59e12,汉明数高达约 10^10000)的界限是根据特定机器选择的,其中希望 i,j,k 是短整数,并且对执行速度也有合理的期望。可以生成更大的表,例如,包含 200 个条目的表将允许 n 高达约 1e18(汉明数高达约 10^85000)。

另一个问题是如何进一步加快速度。一个潜在的领域:事实证明,某些表条目比其他条目更频繁地被命中,并且它们有相应更大的后继列表要检查。例如,当生成第一个 1.59e12 数字时,该条目被 46% 的迭代命中:

{-7470,2791,1312}

它有 23 个可能的不同继任者。也许某种基于其他参数(例如,以前遍历的条目的历史)缩小范围的方法会有所帮助,尽管对于昂贵的操作来说空间不大。

编辑#2:

有关生成表格的一些信息,基本上有六类分数 2^i*3^j*5^k 其中 i,j,k 是正整数或负整数:分子中只有 2,3 或 5 的分数,和分母中只有 2,3 或 5 的分数。例如,对于分子中只有 2 的类:

f = 2^i/(3^j*5^k), i > 0 并且 j,k >= 0

计算这类分数的区间的 AC 程序在这里。对于高达约 10^10000 的汉明数,它会在几秒钟内运行。它可能会变得更有效率。

对其他 5 类分数重复类似的过程会产生六个列表。按间隔大小将它们全部排序并删除重复项会产生完整的表格。

4

1 回答 1

0

三元组枚举是~ n 2/3但波段的排序是~ n 2/3 log (n 2/3 )~ n 2/3 log n即使使用~ n 1/3频带空间方案,这显然也不会改变。

实际上,经验复杂性在实践中被视为~ n 0.7

我还没有完全理解你的算法,但你提供的证据强烈表明纯~ n 2/3操作,这绝对会构成对以前最先进技术的明显和显着的改进。

在此处输入图像描述

在我看来,如果需要生成整个序列以找到您的算法所基于的“间隔”(比率),情况并非如此。但是,由于您是独立生成它们的,正如您后来的编辑似乎暗示的那样,这根本不是障碍。

更正:如果我们只对序列的第n个成员感兴趣,则不需要完整的带;O(n) 选择第 k 大算法确实存在。

于 2017-11-12T18:09:37.630 回答