数字的完美幂,可以适合64位大小的整数(使用优先级队列)

时间:2012-10-19 05:19:49

标签: algorithm sorting priority-queue

我们如何打印出所有可以表示为64位长整数的完美幂:4,8,9,16,25,27 ......完美的力量是一个可以写成ab的数字对于整数a和b≥2。 这不是一个家庭作业问题,我在算法设计书的求职面试问题部分找到了它。提示,该章基于优先级队列。

我所拥有的大多数想法都是二次性的,它们会一直寻找能力,直到它们停止适合64位,但这不是面试官所要求的。另外,我无法理解PQ在这里会有什么帮助。

3 个答案:

答案 0 :(得分:4)

使用小优先级队列,每个电源一个条目,是列出数字的合理方法。请参阅以下python代码。

import Queue             # in Python 3 say:  queue
pmax, vmax = 10, 150
Q=Queue.PriorityQueue(pmax)
p = 2
for e in range(2,pmax):
    p *= 2
    Q.put((p,2,e))

print 1,1,2
while not Q.empty():
    (v, b, e) = Q.get()
    if v < vmax:
        print v, b, e
        b += 1
        Q.put((b**e, b, e))

使用上面代码中的pmax,vmax,它会产生以下输出。对于提出的问题,请将pmaxvmax替换为642**64

1 1 2
4 2 2
8 2 3
9 3 2
16 2 4
16 4 2
25 5 2
27 3 3
32 2 5
36 6 2
49 7 2
64 2 6
64 4 3
64 8 2
81 3 4
81 9 2
100 10 2
121 11 2
125 5 3
128 2 7
144 12 2

该方法的复杂性为O(vmax ^ 0.5 * log(pmax))。这是因为完美正方形的数量优于完美立方体的数量,第四次幂等,并且对于每个正方形,我们对getput队列执行O(log(pmax))工作操作。对于更高的权力,我们在计算b**e时执行O(log(pmax))工作。

vmax,pmax =64, 2**64时,将有大约2 *(2 ^ 32 + 2 ^ 21 + 2 ^ 16 + 2 ^ 12 + ...)队列操作,即大约2 ^ 33个队列操作。

补充说明:本说明涉及cf16的评论,“只有一句话,我不认为”完美正方形的数量优于完美立方体的数量,第四权力等。“他们都是无限的。但是,如果我们考虑有限集“。确实,在整体数学方案中,基数是相同的。也就是说,如果P(j)是所有j'整数幂的集合,则所有整数P(j) == P(k)的基数为j,k > 0。任何两组权力的要素可以相互对应.1。

然而,当按升序计算完美的权力时,无论有多少计算,有限或无数,传递方块的工作都支配任何其他权力的工作。对于任何给定的 x x 区域内的完美 k th 幂的密度随着呈指数下降> k 增加。随着 x 增加, x 区域内的完美 k th 幂的密度与(成正比> x 1 / k )/ x ,因此与正方形相比,第三种力量,第四种力量等变得非常罕见 x 增加。

作为一个具体的例子,在1e8和1e9之间的完美权力中,(2; 3; 4; 5; 6)次幂的数量约为(21622; 535; 77; 24; 10)。 1e8和1e9之间的平方数超过正方形的任何高于正方形的平方数的30倍。下面是两个数字之间的完美平方数的比率,相对于更高的完美幂的数量:10 15 -10 10,r≈301; 10¹⁵-10²⁰,r≈2K; 10²⁰-10²⁵,r≈15K; 10²⁵-10³⁰,r≈100K。简而言之,随着 x 的增加,当完美权力按升序递送时,正方形越来越占主导地位。

答案 1 :(得分:2)

优先级队列有助于,例如,如果要避免输出中的重复项,或者如果要列出特别排序的值。

优先级队列通常可以通过排序替换,反之亦然。因此,您可以生成 b 的所有组合,然后对结果进行排序并删除相邻的重复项。在这个应用程序中,这种方法似乎略有但可能没有像one of the sister answers那样在记忆中效率低下。

如果您设法删除重复项,优先级队列可以优于排序;或者如果你想避免存储和处理要在内存中生成的整个结果。 other sister answer是后者的一个例子,但只需略微修改即可轻松完成。{/ p>

这使得一个占用大约16 GB RAM的阵列和一个少于64个项目的队列在最坏情况下占用几千字节的区别。内存消耗的这种巨大差异也转化为RAM访问时间与缓存访问时间差异,因此即使底层数据结构通过维护自身而需要更多指令与初始算法相比需要更多指令,内存精益算法可能会更快地结束使用排序。

由于输入的大小是固定的,因此从技术上讲,您认为的方法本质上是二次方的。有两个嵌套循环不会使算法成为二次方,直到你可以说每个这样的循环的上限与输入大小成比例,并且通常甚至不是。)真正重要的是最内层逻辑实际执行的次数。

在这种情况下,竞争是在可行常数和不可行常数之间。

答案 2 :(得分:1)

我能看到优先级队列的唯一方法就是你想要在可用时打印数字,严格按顺序增加,当然也不打印任何数字两次。所以你从一个素数发生器开始(使用eratosthenes的筛子或一些更智能的技术来生成序列2,3,5,7,11 ......)。首先,将一个表示2 ^ 2 = 4的事实的三元组放入队列中。然后重复从队列中删除最小项目(具有最小取幂结果的三元组),打印它,将指数增加1并将其放回队列(其优先级由新结果确定)的过程幂)。您将此过程与根据需要生成新素数的过程交错(在输出p ^ 2之前的某个时间)。

由于我们可能拥有的最大指数基数为2 ^ 32(2 ^ 32)^ 2 = 2 ^ 64,因此队列中元素的数量不应超过小于2 ^ 32的素数,是evidently 203,280,221,我猜这是一个易处理的数字。