查找具有多种因素的集合成员的所有产品

时间:2015-06-02 07:50:48

标签: algorithm recursion sum mathematical-optimization

给定一组数字S,如何找到这些数字的所有可能产品(具有任何或所有因素的多重性)低于给定的n

例如,给定S = {2, 3, 5, 7, 11}, n = 12,排序后我想看:

{ 1, 2, 3, 2^2, 5, 2*3, 7, 2^3, 3^2, 2*5, 11, 3*2^2 }

如果S的大小是已知的小常数,我可以使用:

int p,sum=0;
for(int i[0] = 0; p <= n; i[0]++){
  for(int i[1] = 0; p <= n; i[1]++){
    for(etc.){...
      p = pow(S[0],i[0])*pow(S[1],i[0])*pow(...
      // do what you wanted to with p here
      // in my case:
      for(int j = 0; j < SIZE_OF_I; j++){
        if(i[j] > 0){ p *= S[i] - 1; p /= S[i]; }
      }
      sum += p;
    }
  }
}

但我需要它适用于任意大小的S。直觉上,它感觉像递归问题,但我不知道如何开始。

我应该指出的一件事是Project Euler的,所以我无法获得数学方面的帮助。

2 个答案:

答案 0 :(得分:1)

您可以使用优先级队列系统地构建系列。
我的想法是始终在队列的顶部生成最小的元素,当你处理它时,将这个数字加到队列中乘以S中的所有因子。

伪代码:

Create a priority queue (min heap) q
Add 1 to q
set last=0
while q.top() <= n:
    current = q.popHead()
    if current == last:
        continue
    last = current
    yield current
    for each x in S:
        q.add(x*current)

该算法将生成所有可以在S中按元素升序排列的元素,并按升序排列。

改进建议:

  • 使用set确保没有任何元素插入到队列中,而不是使用我在此处提供的last补丁。
  • 注意它可以以某种方式改进,因此您不需要优先级队列, 但只有| S |队列,如果| S |通过有规律,相当小 每个因素的队列,并在处理数字时 - 将其添加到每个因子 队列乘以其因子。

答案 1 :(得分:1)

如果您只需要最终产品,可以使用递归功能:

function prod(base[], n, limit) {    
    if (base.length > 0 && n <= limit) {
        process(n)
        for (i = 0; i < base.length; i++) {
            prod(base[i:], n * base[i], limit)
        }
    }
}

这将处理产品,但不按顺序处理。这基本上是您的嵌套循环变体,表示为递归。一旦超过限制,递归就会停止。 (伪代码符号base[i:]表示从i元素到结尾的子数组。)

如果您需要有关使用的素因子和尊重指数的信息,您应该传递一个额外的指数数组,您必须为每个递归调用调整这些指数。