我正在寻找一种算法(或者更好的是,代码!)用于生成权力,特别是具有大于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整数平方根函数。
答案 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
来实现您的需求。
使用列表的第一个索引作为键构造最小堆,并且在提取最小值之后,我们删除第一个元素,将第二个元素作为键,然后重新排列堆以获得下一个最小值。 重复此过程,直到我们得到所有数字。