C# 项目Euler#3卡住

C# 项目Euler#3卡住,c#,C#,我真的不想这样,体育课的重点当然是我应该自己解决问题 前两个问题我只用了不到一个小时就解决了,不幸的是我完全陷入了问题3。现在我尝试了传统的按试除法,当然这太慢了,我尝试了通过除以sqrt(n)来优化按试除法,但它仍然太慢,无法获得最高的素因子600851475143 现在我甚至试着用埃拉托什尼的筛子来做这个,我不得不承认我几乎不理解,但它仍然没有切掉它,首先,“标记”数字的数量会导致抛出异常,因为当你试图生成所有高达600851475143的素数时,条目的数量会变得巨大 我被卡住了,坦率地说,

我真的不想这样,体育课的重点当然是我应该自己解决问题

前两个问题我只用了不到一个小时就解决了,不幸的是我完全陷入了问题3。现在我尝试了传统的按试除法,当然这太慢了,我尝试了通过除以sqrt(n)来优化按试除法,但它仍然太慢,无法获得最高的素因子600851475143

现在我甚至试着用埃拉托什尼的筛子来做这个,我不得不承认我几乎不理解,但它仍然没有切掉它,首先,“标记”数字的数量会导致抛出异常,因为当你试图生成所有高达600851475143的素数时,条目的数量会变得巨大

我被卡住了,坦率地说,我现在正处在一个开始对此感到恼火的地方

这是我的密码:

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;
        }
类程序
{
//13195的主要因子为5、7、13和29。
//数字600851475143中最大的素因子是什么?
静态void Main(字符串[]参数)
{
Console.WriteLine(GetHighestPrimeFactor(600851475143.ToString());
Console.ReadKey();
}
静态列表GeneratePrimeNumber(长n)
{
//让我们用埃拉托斯烯筛来做这个
var markedNumbers=新列表();
var primes=新列表();
用于(长i=n/2;i
我自己也读过关于埃拉托什尼筛的书,但我对素因子分解的技术知之甚少。我不确定从生成所有已知素的列表开始是一种好的技术。我不是说这是坏的,我只是怀疑也许更实用的技术不会采用这种方法,因为它会我们会有巨大的空间需求

因此,撇开这一点不谈,我将为素数列表的内存使用问题提出一些修复建议

例如,我会将GeneratePrimeNumber的结果写入分段文件,而不是将它们添加到内存列表中,每个文件都包含一些素数块(相当大,但在易于加载到内存的范围内)。也许第一行是关于文件中最大/最小素数的一些信息

在GeneratePrimeNumbers中,从包含最大素数的页面开始(仅将该页面从文件加载到列表中,选择一个C#数据类型,该类型的.Contains有O(1)个时间,我认为一个哈希集会很好),当您向后工作并跨到新段时,请删除当前页面的素数列表并加载新页面的素数。这将解决您的内存使用问题。如果您确保每个页面包含相同数量的素数(或自上一页起的最大数量可能是部分的话)然后,您可以重用现有列表,或者使用容量==将列表初始化为页面大小。无论您使用何种数据结构,它可能在构造函数中有一个容量选项,您希望传递该选项,因为它将确保它预先请求所需的内存量。如果您有300个素数,并且没有设置capcity,则当您添加到列表中时,列表的内部数组大小会加倍。例如,当列表跨过256时,它会在内部创建一个新的512项数组,并将256项复制到新的512项数组。这意味着当跨过此边界时,列表使用的内存量是原来的数组和新的arr的三倍ay是旧阵列的2倍。拷贝完成后,它不需要旧阵列。关键是,如果不预先设置容量,那么当您只需要大约三分之一的可用内存时,可能会出现内存不足异常

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

体育课的重点是我应该自己解决问题

对,这里是一些提示而不是答案

我已经尝试通过除以sqrt(n)来通过试验优化除法

我看不出这有什么帮助。假设你试图找到74的最大素数因子。74的平方根是8点左右。74除以8有什么帮助

现在我甚至试着用埃拉托什尼的筛子来做这个

筛子是用来寻找素数的。你的理论是,你要找到所有的素数,直到所需的数,然后找到最大的素数除以这个数吗

对于一个大的数字来说,这在计算上太昂贵了

以下是你的提示:

  • 如果一个数n>0是素数,那么它就是它自己的最大素数因子

  • 如果一个n>0的数字是复合的,那么它就是x*y,其中两个都不是1

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

  • n的最大素数因子等于最大素数fac