找到复合数的最小值

时间:2014-03-16 06:11:45

标签: algorithm numbers primes

如果有一些给定的素数:2,3,5,7 是否有一种有效的方法可以找出大于某个给定数字的最小复合数,除了允许的素数之外,它没有任何素数因子。

例如:
给定素数集:2, 3, 5, 7 如果我们想要找到一个必须大于或等于85的复合数,并且除了2,3,5或7之外没有素数因子,答案应该是90.
因为

85 = 5 * 17 (wrong)  
86 = 2 * 43 (wrong)  
87 = 3 * 29 (wrong)  
88 = (2 ^ 3) * 11 (wrong)  
89 = 89 (wrong)  
90 = 2 * (3 ^ 2) * 5 (correct)

3 个答案:

答案 0 :(得分:1)

  1. 从起始编号开始。

  2. 使用trival除法计算当前数字。

  3. 如果当前的数字是复合数并且所有因子都在给定列表中,请停止,当前数字就是答案。

  4. 在当前号码中添加一个。

  5. 转到第2步。

答案 1 :(得分:1)

对于你的小数字的例子,蛮力方法可能没问题:测试85以上的所有数字。您不需要确定所有因素。通过连续划分列表中的素数,您可以查看是否可以将数字n降为1。

或者,您可以使用自下而上的方法:有效的合成数字是:

2^a2 * 3^a3 * 5^a5 * 7^a7

您现在可以递归探测所有集{a2, a3, a5, a7}。从{0, 0, 0, 0}开始,产生1,设置索引为0.然后通过递增当前设置索引处的指数并通过增加设置索引进行探测,如果这并不意味着你超越了列表的边界。

当您遇到等于或高于阈值的数字时,请不要进一步递减。

在伪代码中:

function spread(p[], ix, num, lim)
{
    if (num >= lim) {
        return min;
    } else {
        m1 = spread(p, ix, k * p[ix], lim, min);

        ix++;
        if (ix == p.length) return m1

        m2 = spread(p, n, ix, num, lim, min);
        return min(m1, m2);
    }
}

min = spread([2, 3, 5, 7], 0, 1, 85)

这种方法在你的例子中不会给你带来太大的影响,但对于较大的素数和案例来说应该更好,其中最小值不接近阈值。

答案 2 :(得分:0)

您正在找到最小数字2 ^ i 3 ^ j 5 ^ k 7 ^ l,它大于或等于某些N.

我们可以按顺序处理这些数字,直到我们得到一个大于N的数字。

最小数字是1,对应于(i,j,k,l)=(0,0,0,0)。 我们现在将这个元组推到最小堆H并添加到集合S中 (例如,使用哈希表实现)。

我们现在重复以下内容,直到找到大于N的数字:

  • 从堆H
  • 中弹出最小元素(i,j,k,l)
  • 添加元组(i + 1,j,k,l),(i,j + 1,k,l),(i,j,k + 1,l)和(i,j,k,l +1)到H和S,如果它们还不在S中。

这确保我们以正确的顺序考虑数字,因为每次删除数字/元组时,我们都会将所有新的候选者添加到堆中。

这是python中的一个实现:

import heapq
N = 85
S = set([(0,0,0,0)])
H = [( 1 , (0,0,0,0) )]
while True:
    val,(i,j,k,l) = heapq.heappop(H)
    if val >= N:
        break
    if (i+1,j,k,l) not in S:
        S.add((i+1,j,k,l))
        heapq.heappush(H,( val*2 , (i+1,j,k,l) ) )
    if (i,j+1,k,l) not in S:
        S.add((i,j+1,k,l))
        heapq.heappush(H,( val*3 , (i,j+1,k,l) ) )
    if (i,j,k+1,l) not in S:
        S.add((i,j,k+1,l))
        heapq.heappush(H,( val*5 , (i,j,k+1,l) ) )
    if (i,j,k,l+1) not in S:
        S.add((i,j,k,l+1))
        heapq.heappush(H,( val*7 , (i,j,k,l+1) ) )

print val # 90

由于序列的大小呈指数级增长,因此迭代次数不会超过O(log N)。在每次迭代中,我们最多向H和S添加3个项,因此堆永远不会包含多于O(3 log N)个项。因此,每个堆/集操作的成本不会超过O(log log N),从而确保整个时间复杂度为O(log N * log log N)。