项目欧拉#3 STUCK

时间:2014-04-25 22:18:17

标签: c#

我真的不想让它来到这里,PE当然是我应该尝试自己解决问题。

前两个我在不到一个小时内完成了管理,不幸的是我完全陷入了问题3.现在我尝试了传统的分区试验方法,当然这太慢了,我试过优化通过除以 sqrt(n)的试验划分,但仍然太慢,无法获得600,851,475,143的最高素数因子。

现在我甚至试图使用 Eratosthenes的筛子这个,我不得不承认我几乎不理解,但它仍然没有削减它,首先"标记为"数字会导致抛出异常,因为当您尝试生成高达600,851,475,143的所有素数时,条目数量会变得巨大。

我被困了,坦率地说,我现在正处于开始对此感到恼火的地方..

这是我的代码:

class Program
    {
        // The prime factors of 13195 are 5, 7, 13 and 29.
        // What is the largest prime factor of the number 600851475143 ?
        static void Main(string[] args)
        {

            Console.WriteLine(GetHighestPrimeFactor(600851475143).ToString());
            Console.ReadKey();
        }

        static List<long> GeneratePrimeNumbers(long n)
        {
            // Let's use the Sieve of Eratosthenes for this
            var markedNumbers = new List<long>();
            var primes = new List<long>();

            for (long i = n / 2; i < n; i++)
            {
                // If this is false then this is a prime number, add it to the list of primes
                if (!markedNumbers.Contains(i)) 
                {
                    primes.Add(i);

                    for (long j = i; j <= n; j+= i)
                    {
                        markedNumbers.Add(j);
                    }
                }
            }

            return primes;
        }

        static long GetHighestPrimeFactor(long n)
        {
            var primes = GeneratePrimeNumbers(n);

            // Loop backwards and return when we hit the first prime number
            for (long i = n / 2; i > 1; i--)
            {
                if (n % i == 0)
                {
                    if (primes.Contains(i))
                    {
                        return i;
                    }
                }
            }

            //Code should not reach this point of execution
            return -1;
        }

2 个答案:

答案 0 :(得分:2)

  PE的当然点是我应该自己尝试解决问题。

是的,所以这里有一些提示而不是答案。

  

我试图通过除以sqrt(n)

来优化除法

我不知道这有多大帮助。假设你试图找到最大的素数因子74. 74的平方根是8点。如何将74除以8.something帮助?

  

现在我甚至试图使用Eratosthenes的筛子

Sieve用于查找素数。你的理论是,你会发现所有素数达到所需的数量然后那些找到最大的数字除以?

对于大量人来说,计算成本太高了。

所以这是你的提示:

  • 如果数字n> 0是素数然后它是它自己最大的素数除数。

  • 如果数字n> 0是复合的,然后是x * y,其中两者都不是1.

  • 这两个数字中的一个小于或等于n的平方根。

  • n的最大素因子等于x的最大素因子或y的最大素因子。

如果你不明白为什么其中一个事实是真的,那么在你做之前停下来思考一下。除非你感到寒冷,否则你将永远无法解决接下来的几个欧拉问题。

现在有了这些提示,您应该能够将问题分解为一系列较小的问题。

答案 1 :(得分:0)

我自己已经阅读了关于Eratosthenes筛选的信息,但我对素数分解技术知之甚少。我不确定从生成所有已知质数的列表开始是一个很好的技术。不是说它不好,我只是怀疑可能更实用的技术不采用这种方法,因为它会有巨大的空间需求。

除此之外,我会建议修补素数列表的内存使用问题。

首先,我会将GeneratePrimeNumbers的结果写入分段文件,而不是将它们添加到内存列表中,每个文件覆盖一些素数块(相当大但在容易加载到内存中的范围内)。也许作为第一行有关文件中最大/最小素数的一些信息。

在GeneratePrimeNumbers中,从包含最大素数的页面开始(将该页面从文件加载到列表中,选择一个C#数据类型,其中包含O(1)时间.Contains,我认为HashSet对此有好处),当你向后工作并交叉到一个新的段时,删除当前页面的素数列表并加载素数的新页面。这将解决您的内存使用问题。如果确保每个页面包含相同数量的素数(或者自上一页可能是部分的最大数量),那么您可以重用现有列表或使用容量==初始化列表到页面大小。无论你使用什么数据结构,它都可能在构造函数中有一个容量选项,你想传递它,因为它将确保它预先请求所需的内存量。如果你有300个素数,并且没有设置capcity,那么当你添加它时,列表的内部数组大小会加倍。例如,当它超过256时,它会在内部创建一个新的512项数组,并将256个项复制到新的512个数组。这意味着当跨越这样的边界时,列表使用三倍的内存量,因为它既有旧数组又有新数组,是旧数组的2倍。复制完成后,它不需要旧的数组。重点是,如果你没有预先设置容量,那么当你只需要大约三分之一的可用内存时,你可能会出现内存异常。

我可能会让GeneratePrimeNumbers检查预先存在的文件,如果传入的数字较大,那么只需跳到最大的现有页面并写入其他页面直到该值。我可能有一个索引文件,列出页面和开始/结束素数,这样你就不必读取一堆大文件来执行此检查,但我认为你可以通过开始/结束每个文件作为第一行,只读取第一行然后关闭文件。