如何找出一些给定素数的最近可能组合到10000?

时间:2011-11-02 22:35:08

标签: c# algorithm math

public int Partition1 {get;set;}
public int Partition1 {get;set;}

private void SetPartitions(List<int> primeNumbers)
{       
    this.Partition1 = // get the product of the prime numbers closest to 10000
    this.Partition2 = // get the product of the remaining prime numbers            
}

SetPartitions方法接受一个素数数组,如2,3,5,2851,13。

在上面的例子中,它应该分配:

this.Partition1 = 2851 * 3; // which is 8553 and closest possible to 10000
this.Partition2 = 2 * 5 * 13;

如何实现逻辑?

6 个答案:

答案 0 :(得分:1)

然后遍历从10,000到2的每个数字。对于每个数字,测试以查看数字的素数因子分解是否是给定列表的子集。如果是,那么我们就找到了答案。

Partition1是该数字的主要因素。 Partition2只是primeNumbers - Partition1

这是伪代码:

for n=10000 to 2
    factors = prime_factorization(n)

    if( factors is subset primeNumbers ) {
        partition1 = factors
        partition2 = primeNumbers - factors
        return (partition1,partition2)
    }

答案 1 :(得分:1)

我的解决方案如下

private void SetPartitions(List<int> primeNumbers, int bound)
{
    int[] mods = new int[primeNumbers.Count];
    for(int i = 0; i < primeNumbers.Count; i++)
        mods[i] = bound % primeNumbers[i];

    int count = bound;
    do
    {
        int temp = count;

        for(int j = 0; j < mods.Length; j++)
            if(mods[j] == 0) 
                temp /= primeNumbers[j];

        if(temp == 1)
        {
            this.Partition1 = count;
            for(int k = 0; k < mods.Length; k++)
                if(mods[k] != 0)
                    temp *= primeNumbers[k];
            this.Partition2 = temp;
            return;
        }
        else
        {
            for(int k = 0; k < mods.Length; k++)
                mods[k] = (mods[k] == 0) ? primeNumbers[k] - 1 : mods[k] - 1;
            count--;
        }
    }while(true);
}

答案 2 :(得分:0)

我认为这是作业。答案是2 * 4999(9998),通过检查。

蛮力技术(应该)显而易见。获取所有素数x的列表,使得0 <= x <= 5000(因为你在这里寻找因子,你将是数字乘以...并且因为最小的素数是2,所以你不需要担心任何大于5000的事情)。对于列表中的每个项目,再次遍历列表,检查列表中的每个y。将它们相乘并记录产品与10000之间的差值。保持最小值。

另一种方法是从10000开始并计算其素因子(如果有的话)。

http://mathworld.wolfram.com/PrimeFactorization.html

http://mathworld.wolfram.com/PrimeFactorizationAlgorithms.html

例如:

int i = 10000 ;
int[] primeFactors = null ;
while ( i > 0 && ( primeFactors == null || primeFactors.Length == 0 ) )
{
  primeFactors = ComputePrimeFactorsOf( i ) ;
}
// if primeFactors is contains data, there's your solution

答案 3 :(得分:0)

听起来像knapsack problem的重新制定。虽然你的是乘法计算素数的对数,而目标数会将其转化为加法问题。

但即使一般的背包问题是 hard ,你的特定问题子集也可能有一个快速的解决方案。

答案 4 :(得分:0)

2^14 = 16384起,您最多可以有13个素数因子,其中最多5个可以是不同的(因为2*3*5*7*11*13 = 30030 > 10000)。最简单的解决方案是迭代所有组合。如果您希望其中一个产品最接近10,000,那么您可以浏览所有产品。如果您只想要一个两个分区的产品都小于10,000的产品,您可以在有解决方案后立即停止。即使没有任何优化,在今天的机器上也只需要几分之一秒。

答案 5 :(得分:0)

 internal static void GetPartitionsClosestTo9999(List<long> primeFactors, out long partition1, out long partition2)
        {
            for (var index = 9999; index >= 2; index--)
            {
                var primeFactorsForCurrentIndex = GetPrimeFactors(index);
                var isSubset = IsSubSet(primeFactorsForCurrentIndex, primeFactors); //!primeFactorsForCurrentIndex.Except(primeFactors).Any();
                if (isSubset)
                {
                    partition1 = index;
                    foreach (var primeFactorForCurrentIndex in primeFactorsForCurrentIndex)
                    {
                        primeFactors.Remove(primeFactorForCurrentIndex);
                    }
                    partition2 = GetProduct(primeFactors);
                    return;
                }
            }
            throw new ApplicationException("No subset found.");
        }

        static bool IsSubSet<T>(ICollection<T> set, IEnumerable<T> toCheck)
        {
            return set.Count == (toCheck.Intersect(set)).Count();
        }