算法尽可能地考虑几个因素

时间:2012-09-14 13:05:57

标签: algorithm

是否有一个已知算法将整数分解为尽可能少的因素(不一定是素数),其中每个因子都小于某个给定的常数N?

我不关心质数因子大于N的数字。另外,我不处理数百万以上的数字,并且因子分解是处理初始化的一部分,所以我并不特别担心计算复杂性。

编辑:要清楚。我已经有代码找到了主要因素。我正在寻找一种方法,将这些因素尽可能少地组合成复合因子,同时保持每个因子小于N.

3 个答案:

答案 0 :(得分:7)

您可以将问题分为两部分来解决问题:

  1. 使用standard techniques中的任何一个将您的数字分解为素数。对于只有几百万的人来说,试验部门完全没问题。

  2. 取每个因子的对数,并将pack them into bins大小记录 N

  3. 现在,bin打包是NP-hard但实际上可以使用简单的技术找到好的近似解决方案:first-fit算法打包不超过最佳bin数的11/9倍(加上一个bin )。

    这是Python中的一个实现:

    from math import exp, log, sqrt
    import operator
    
    def factorize(n):
        """
        Factorize n by trial division and yield the prime factors.
    
        >>> list(factorize(24))
        [2, 2, 2, 3]
        >>> list(factorize(91))
        [7, 13]
        >>> list(factorize(999983))
        [999983]
        """
        for p in xrange(2, int(sqrt(n)) + 1):
            while n % p == 0:
                yield p
                n //= p
            if n == 1:
                return
        yield n
    
    def product(s):
        """
        Return the product of the items in the sequence `s`.
    
        >>> from math import factorial
        >>> product(xrange(1,10)) == factorial(9)
        True
        """
        return reduce(operator.mul, s, 1)
    
    def pack(objects, bin_size, cost=sum):
        """
        Pack the numbers in `objects` into a small number of bins of size
        `bin_size` using the first-fit decreasing algorithm. The optional
        argument `cost` is a function that computes the cost of a bin.
    
        >>> pack([2, 5, 4, 7, 1, 3, 8], 10)
        [[8, 2], [7, 3], [5, 4, 1]]
        >>> len(pack([6,6,5,5,5,4,4,4,4,2,2,2,2,3,3,7,7,5,5,8,8,4,4,5], 10))
        11
        """
        bins = []
        for o in sorted(objects, reverse=True):
            if o > bin_size:
                raise ValueError("Object {0} is bigger than bin {1}"
                                 .format(o, bin_size))
            for b in bins:
                new_cost = cost([b[0], o])
                if new_cost <= bin_size:
                    b[0] = new_cost
                    b[1].append(o)
                    break
            else:
                b = [o]
                bins.append([cost(b), b])
        return [b[1] for b in bins]
    
    def small_factorization(n, m):
        """
        Factorize `n` into a small number of factors, subject to the
        constraint that each factor is less than or equal to `m`.
    
        >>> small_factorization(2400, 40)
        [25, 24, 4]
        >>> small_factorization(2400, 50)
        [50, 48]
        """
        return [product(b) for b in pack(factorize(n), m, cost=product)]
    

答案 1 :(得分:1)

我不知道是否有既定算法,但我会尝试以下

public static List<Integer> getFactors(int myNumber, int N) {
    int temp=N;
    int origNumber=myNumber;        
    List<Integer> results=new ArrayList<Integer>();
    System.out.println("Factors of "+myNumber+" not greater than "+N);
    while (temp>1) {            
        if (myNumber % temp == 0) {
            results.add(temp);
            myNumber/=temp;                                
        } else {
            if (myNumber<temp) {
                temp= myNumber;                    
            } else {
                temp--;
            }
        }
    }
    for (int div : results) {
        origNumber/=div;
    }
    if (origNumber>1) {
        results.clear();
    }        
    return(results);
}

我希望它有所帮助。

答案 2 :(得分:0)

那么,如果你能找到一个因素,你就完成了,因为第二个因素就是你的数字除以第一个因子。为了使它快速,只需使用一个素数筛子。如果您的最大数量在数百万的范围内,我猜筛子不是很大。