按顺序生成一系列数字(幂)

时间:2011-01-27 06:07:47

标签: algorithm language-agnostic optimization math

我正在寻找一种算法(或者更好的是,代码!)用于生成权力,特别是具有大于1的奇数指数的数字:第三权力,第五权力,第七权力等等。那么我想要的输出是

8, 27, 32, 125, 128, 216, 243, 343, 512, 1000

等等达到指定的限制。

我不想将权力存储在列表中并对它们进行排序,因为我制作的内容太多而不适合内存 - 希望限制为10 30 左右,对应于内存要求≈1TB。

我的基本想法是让一个数组保存每个指数的当前数字(从2开始),从3开始,然后上升到限制的二进制日志。在每个步骤中,我遍历指数数组,找到产生最小功率的数据(找到pow(基数,指数)或更可能指数* log(基数),可能记住这些值)。在那时调用'output'函数,它实际上会用数字进行计算,但当然你不需要担心。

当然,由于涉及的数字范围,必须使用bignums - 内置于语言,库中或自行编排。相关的代码或代码片段将不胜感激:我觉得这个任务类似于一些经典问题(例如,汉明的生成数字的问题,形式为2 x 3 y 5 z )并且可以有效地解决。我在这里与语言无关:我的'输出'函数需要的是数组,减法,bignum-word比较和bignum整数平方根函数。

3 个答案:

答案 0 :(得分:3)

您的示例缺少64 = 4 ^ 3和729 = 9 ^ 3.

你想要以数字顺序遍历的所有{n ^ m}的集合,m odd,n integral和n> 1.我们知道(对于n> 1)增加n m会增加这个值,但是由于计算不足,我们无法比较其他数据。

有两种明显的“双重”方法可以做到这一点:跟踪你考虑的最高基数n,并且对于所有小于此的基数,要考虑下一个指数m。然后选择最小的一个,并将其与n ^ 3进行比较。或者,反过来 - 跟踪最高指数m,并且对于小于该指数的每个指数,跟踪所使用的最高基数,并找到最小的基数,并将其与添加2 ^ m进行比较。

为了有效地跟踪这些数字,您需要将它们保存在priority queue中。现在,您仍然希望一次最小化优先级队列中的条目数,因此我们想要弄清楚这两种方法中的哪一种更好地完成了这项工作。事实证明,需要更高的n值才能使它达到给定的点。在数字k处,所见的最大值m将是k的log_2,而所见的最大值n将是k ^(1/3)。

所以,我们有一个带元素(v,n,m)的优先级队列,其中值v = n ^ m。

add_priority_queue(2^3, 2, 3)
for m in 5, 7, ....
    v = 2^m
    while value(peek(queue)) <= v:
        (v1, n1, m1) = pop(queue)
        if v1 != v print v1
        add_priority_queue((n1+1)^m1, n1+1, m1)
    add_priority_queue(2^m, 2, m)

注意我们需要检查v1 = v:我们可以有2 ^ 9 = 512 = 8 ^ 3,只有一个应该打印出来,对吗?

Haskell实现,从hackage抓取随机优先级队列。

import Data.MeldableHeap

dropMin q = maybe empty snd (extractMin q)

numbers = generate_values (insert (2^3, 2, 3) empty) 5

generate_values q m = case findMin q of
    Nothing -> []
    Just (v1, n1, m1) -> case compare v1 (2^m) of
        EQ -> generate_values (insert ((n1+1)^m1, n1+1, m1) (dropMin q)) m
        LT -> v1 : generate_values (insert ((n1+1)^m1, n1+1, m1) (dropMin q)) m
        GT -> 2^m : generate_values (insert (3^m, 3, m) q) (m + 2)

main = sequence_ (map print numbers)

我在8分钟后运行了177403008736354688547625(即23位数)和1.3 GB明文输出

答案 1 :(得分:1)

deque numbers // stores a list of tuples - base number, and current odd power value - sorted by the current odd power value

for i = 2 .. infinity
  numbers.push_back (i,i^3) // has to be the highest possible number so far
  while numbers.peek_front[1] == i // front always has the lowest next value
    print i
    node = numbers.pop_front
    node[1]=node[1]*(node[0]^2)
    // put the node back into the numbers deque sorted by the second value in it - will end up being somewhere in the middle

在2,数字将为[2,8]

在3,数字将是[2,9],[3,27] ... 在8,数字将是[2,8],[3,27] ..... [8,8 ^ 3]

你将取下第一个节点,将其打印出来,然后将其放回数字中间,并带有值[2,32]

我认为这会有效并且内存使用合理。

1有一个特殊情况,因为1 ^ N永远不会改变。这也将打印出数字的重复值 - 例如256 - 并且有一些相当简单的方法可以稍微改变算法以删除它们。

此解决方案是检查每个数字的固定时间,但需要相当多的ram。

答案 2 :(得分:1)

考虑数字k数字的2 .. k+1列表。每个列表i代表数字i+1的权力。由于每个列表都是一个有序的使用k-way merging with min heap来实现您的需求。

使用列表的第一个索引作为键构造最小堆,并且在提取最小值之后,我们删除第一个元素,将第二个元素作为键,然后重新排列堆以获得下一个最小值。 重复此过程,直到我们得到所有数字。