【问题标题】:Wrong Answer for Project Euler 50Project Euler 50 的错误答案
【发布时间】:2013-04-03 00:59:41
【问题描述】:

我正在尝试 Euler 项目的第 50 题。

素数41,可以写成六个连续素数之和:

41 = 2 + 3 + 5 + 7 + 11 + 13 这是连续的最长和 加到低于一百的素数上的素数。最长的总和 加到素数上的小于一千的连续素数包含 21 项,等于 953。100 万以下的质数可以是 写成最连续素数之和?

这是我的代码:

    public class consPrime
    {
        static int checker(int ar[],int num,int index) //returns no.of consecutive
        {                                              //primes for the given num  
            while(true)
        {

        int temp=num;

        for(int i=index;i>=0;i--)
        {
            temp=temp-ar[i];

            if(temp==0)
            {
                return (index-i+1);
            }               
        }           
        index--;
        if(index==0)
        return 0;           
        }
    }

    public static void main(String args[])
    {               
        int n=100000;
        int ar[]=new int[n];
        int total=0;int flag;

        for(int i=2;i<1000000;i++)   //Generates an array of primes below 1 million
        {
            flag=1;

            for(int j=2;j<=Math.sqrt(i);j++)
            {
                if(i%j==0)
                {
                    flag=0;
                    break;
                }                   
            }
            if(flag==1)
            {
                ar[total]=i;
                total++;
            }               
        }

        int m=0;
        int Big=0;

        for(int i=total;i>=0;i--) //Prints the current answer with no.of prime
        {
            m=checker(ar,ar[i],i-1);
            if(Big<=m)
            {Big=m;
                System.out.println(ar[i]+"     "+Big);
            }
        }           
    }       
}

基本上,它只是创建一个包含最多 1000000 的所有素数的向量,然后循环遍历它们以找到正确的答案。答案是 997651,计数应该是 543,但我的程序分别输出 990707 和 75175。可能有什么问题?

【问题讨论】:

  • 您是否验证过您的素数数组已正确生成?您是否已验证您的 checker 方法是否按您的预期工作?这个问题需要缩小范围。
  • 我完全不确定你的程序是如何工作的。在这个循环中:for(int i=total;i&gt;=0;i--)i 变为0 时,对checker 的调用将-1 作为index 传递。然后在checker 方法中,此循环for(int i=index;i&gt;=0;i--)-1 开头,您尝试检索ar[-1]。那时您没有收到Out Of Bounds 异常吗?
  • 我运行程序时没有错误......它工作正常......但显然会产生错误的答案!

标签: java algorithm numbers


【解决方案1】:

几个大问题:

  1. 首先要解决一些小问题:学会正确缩进代码,学会使用正确的命名约定。在 Java 中,变量名使用 camelCasing 而类型名使用 PascalCasing。

  2. 你的逻辑有很多问题:你循环遍历素数数组,直到你达到零或直到循环遍历数组中的所有数字。但是,请注意,整数存在下溢/上溢。有可能“温度”不断扣除并变成负数,然后变成正数,如此等等并达到零。但这不是正确的答案

  3. 您只尝试查找以索引 - 1 结尾的连续数字。例如,要检查索引 10 处的素数,您将从索引 9 向后查找连续素数。但是,与您的目标数相加的连续素数很少(实际上几乎从不,除了 5)包含“先前的”素数。整个逻辑完全是错误的。

  4. 更不用说你为checker传递的参数不正确,用户@pm-77-1的评论中提到了这一点

【讨论】:

  • 对于您的第 3 点:外部循环中的索引递减。所以我不明白如果我从前一个素数开始有什么关系,因为最终将检查该数字以下的所有连续素数集!
  • 它递减,但您现在正在做的是,例如,检查索引 10 的素数:首先检查索引 9,然后检查索引 9、8,然后检查索引 9、8、7 ...。直到您检查索引 9,8,7,...1,0 或者如果您达到零。这意味着,您只是从前一个素数向后检查连续数字。然而,正确的连续素数可以来自索引 3-6,告诉我你的逻辑如何找到这个
  • 我检查了我的程序。发生的问题是整数上溢/下溢(正如您在第 2 点中提到的,我没有意识到这一点,感谢您的告知)。至于逻辑,我有 2 个循环,内部循环试图找到从索引到任何数字 n 的连续素数集。如果不可能,则尝试从 index-1 到任何数字 m 找到集合。例如,检查索引为 10 的素数:首先检查集合 9,8,7...n ,如果不满足,则从 8,7,6..m 开始,依此类推。虽然 IndexOutOFBound 现在不幸发生了!
  • 对于你的逻辑,即使你有一个额外的循环级别,它仍然是错误的。如果我的理解是正确的,一个素数可能由多个连续的素数序列组成。例如对于索引 10 处的素数,它可能由 5、6、7 或 1、2、3、4 组成。但是,您只能找到“最后一个”连续序列,这可能会导致错误的结果。对于 IndexOutOfBound,请查看 pm-77-1 的评论。这是直截了当的。
  • 嗯,是的。这是一个缺陷,虽然我之前曾想过,但我觉得这种情况不太可能出现。感谢您的建议。他们真的很有帮助!
【解决方案2】:

这是另一种方法,需要 43 毫秒

它基于以下方法:

1) 素数

2) 它在 O(n2) 中迭代所有数字并计算连续素数。第一个循环更改序列的第一个元素,第二个循环从该位置开始获取元素并将它们添加到总和中。如果总和是素数,并且由最多数量的素数组成,则将其保存在变量中。

import java.util.ArrayList;
import java.util.List;

public class P50 {

    private final static int N = 1_000_000;

    public static void main(String[] args) {
        boolean primes[] = generatePrimes(N);
        List<Integer> primeIntegers = new ArrayList<Integer>();
        for (int i = 0; i < primes.length; i++) {
            if (primes[i]) {
                primeIntegers.add(i);
            }
        }
        int count = 0;
        int sum = 0;
        int finalSum = 0;
        int finalCount = 0;
        int totalPrimes = primeIntegers.size();
        for (int start = 0; start < totalPrimes; start++) {
            sum = 0;
            count = 0;
            for (int current = start; current < totalPrimes; current++) {
                int actual = primeIntegers.get(current);
                sum += actual;
                if ( sum >= N ) {
                    break;
                }
                if ( primes[sum] ) {
                    if ( count > finalCount ) {
                        finalCount = count;
                        finalSum = sum;
                    }
                }
                count++;
            }
        }
        System.out.println(finalSum);
    }

    private static boolean[] generatePrimes(int n) {
        boolean primes[] = new boolean[n];
        for (int i = 0; i < n; i++) {
            primes[i] = true;
        }
        primes[0] = false;
        primes[1] = false;
        // i = step
        for (int i = 2; i * i < n; i++) {
            if (primes[i]) {
                for (int j = i * i; j < n; j += i) {
                    primes[j] = false;
                }
            }
        }
        return primes;
    }

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-01
    • 1970-01-01
    相关资源
    最近更新 更多