如何找到数字可以表示为素数之和的方式?

时间:2011-10-29 21:00:10

标签: primes

  

可能重复:
  Generating the partitions of a number

  

素数总和

     

数字7可以用5种方式表示为素数之和:

     
      
  • 2 + 2 + 3
  •   
  • 2 + 3 + 2
  •   
  • 2 + 5
  •   
  • 3 + 2 + 2
  •   
  • 5 + 2
  •   
     

制作一个程序,计算数字n的数量   表示为素数之和。您可以假设n是一个数字   在0-100之间。你的程序应该打印答案不到一个   第二

     

示例1:
  给出数字:7结果:5

     

例2:
  给出数字:20结果:732

     

例3:
  编号:80结果:10343662267187

我已经遇到这个问题好几个小时了。我无法弄清楚如何从(n-1)获得n。 以下是树搜索前30个数字的总和

0 0 0 1 2 2 5 6 10 16 19 35 45 72 105 152 231 332 500 732 1081 1604 2351 3493 5136 7595 11212 16534 24441

我认为我找到了最大的链条7 = 5 + 2并且以某种方式使用5可以写成5,3 + 2,2 + 3的知识,但不知何故我需要考虑重复的2+ 3 + 2替换。

3 个答案:

答案 0 :(得分:4)

查找动态编程,特别是Wikipedia的页面以及斐波那契序列的示例,并考虑如何在这里适应您的问题。

答案 1 :(得分:2)

好的,这是一个复杂的问题。你问的是如何编写分区函数的代码;我建议你read up on the partition function itself first。接下来,您应该查看计算分区的算法。这是一个复杂的主题,这是starting point ...分区问题是[NP完整] ---这个问题已经asked and answered here,这也可以帮助你从算法开始。

答案 2 :(得分:-1)

有几种选择。既然你知道这个数字介于0到100之间,那么显而易见:作弊,只需制作一个数组并填写数字。

另一种方式是循环。您需要100以下的所有素数,因为小于100的数字不能使用大于100的素数之和来表示。 99不能表示为2和任何大于100的素数之和。

你还知道的是:偶数之和的最大长度是数除以2.因为2是最小的素数。对于奇数,最大长度为(数字-1)/ 2。

EG。 8 = 2 + 2 + 2 + 2,因此总和的长度为4
9 = 2 + 2 + 2 + 3,因此总和的长度为4

如果你想要性能,你可以通过使用GPGPU以另一种方式作弊,这将显着提高性能。

然后他们就是改组方法。如果你知道7 = 2 + 2 + 3,你知道7 = 2 + 3 + 2.要做到这一点,你需要一种计算混乱的不同可能性的方法。你可以存储各种可能性的组合,或者在编写循环时记住它们。

这是一个相对暴力方法(用Java):

int[] primes = new int[]{/* fill with primes < 100 */};
int number = 7; //Normally determined by user
int maxLength = (number % 2 == 0) ? number / 2 : (number - 1) / 2; //If even number maxLength = number / 2, if odd, maxLength = (number - 1) / 2
int possibilities = 0;    

for (int i = 1; i <= maxLength; i++){   
    int[][] numbers = new int[i][Math.pow(primes.length, i)]; //Create an array which will hold all combinations for this length
    for (int j = 0; j < Math.pow(primes.length, i); j++){ //Loop through all the possibilities
        int value = 0; //Value for calculating the numbers making up the sum
        for (int k = 0; k < i; k++){
            numbers[k][j] = primes[(j - value) % (Math.pow(primes.length, k))]; //Setting the numbers making up the sum
            value += numbers[k][j]; //Increasing the value
        }
    }
    for (int x = 0; x < primes.length; x++){
        int sum = 0;
        for (int y = 0; y < i; y++){
            sum += numbers[y];
            if (sum > number) break; //The sum is greater than what we're trying to reach, break we've gone too far
        }
        if (sum == number) possibilities++;
    }
}

我明白这很复杂。我会尝试用一个类比。把它想象成一个密码锁。你知道你必须尝试的最大轮数,因此是“i”循环。接下来,您将了解每种可能性(“j”循环),然后设置各个数字(“k”循环)。 “k”循环中的代码用于从当前可能性(j的值)变为实际数字。输入此轮数量的所有组合后,您将计算是否正确,如果是,则增加可能性。

如果我在代码中犯了任何错误,我会提前道歉。