项目Euler#12运行时非常慢

时间:2014-08-17 14:07:33

标签: c#

我现在正在努力争取我的Project Euler#12代码约3个小时。我实现了为数字超过130个除数的情况节省了几秒钟,我的第一个程序达到2.33秒,现在它在1.169秒内完成。但是我从来没有耐心等待500的除数。如何固定我的代码?我尝试了从n和n + 1得到除数的情况,但它只是减慢了我的程序......这是我的代码。

static bool isPrime(int num) {
        if (num % 2 == 0 && num != 2)
            return false;
        else
            for (int i = num; i < Math.Sqrt(num) + 1; i++) {
                if (num % i == 0)
                    return false;
            }
        return true;
    }

    static void Main(string[] args) {

        Stopwatch time = new Stopwatch();
        time.Start();

        int trianglenumber = 0;
        int divizori = 0;

        for (int i = 3; i < Int32.MaxValue; i+=2) {
            if (isPrime(i) != false) {
                int tempnumber = 0;
                tempnumber = (i * (1 + i)) / 2;
                for (int k = 1; k < tempnumber + 1; k++) {
                    if (tempnumber % k == 0) {
                        divizori++;
                    }
                }

                if (500 < divizori) {
                    trianglenumber = tempnumber;
                    break;
                }
                divizori = 0;
            }
        }
            time.Stop();
            double timp = time.ElapsedMilliseconds ;

            Console.WriteLine(trianglenumber);
            Console.Write("Runtime: " + timp/1000 + " seconds");
            Console.ReadKey();
    } 

3 个答案:

答案 0 :(得分:2)

减速是在你的isPrime()方法中。

通过素数分解来计算计数因子。你会发现计算500个因素的速度要快得多。

http://www.mathsisfun.com/prime-factorization.html

此外,您如何获得三角数应该更简单。

1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ...

注意每个连续数字组之间的差异......

1 + 2 = 3

3 + 3 = 6

6 + 4 = 10

10+ 5 = 15

15+ 6 = 21

等等......看看那个中间数字。

仅供参考,我使用素数分解方法的版本需要大约6ms来找到答案....非常快。

答案 1 :(得分:0)

围绕这个问题的一些Python函数。它使用Counters,完美 高水平的工具来做到这一点。希望这可以帮助您找到密钥增强功能。

from collections import Counter  

def factors(n):
    divisor=2
    while divisor*divisor<=n:
        if n%divisor==0:
            return Counter({divisor:1})+factors(n//divisor)
        divisor += 1
    return Counter({n:1}) # prime number

def nbdiv(factors):
    p=1
    for factor in factors : p *= factors[factor]+1
    return p 

def nbdivtri(n):
    a,b=n,n+1
    if a%2==0 : a//=2
    else: b//=2
    return nbdiv(factors(a)+factors(b))  

答案 2 :(得分:0)

我用小于0.187毫秒的贪婪算法解决了这个问题。

    static void Main(string[] args)
    {
        // 76576500
        long age = 10000;
        double alpha = 1.5;
        double betta = 0.1;
        Random ran = new Random();
        long mmm = long.MaxValue;
        double RR = 0;
        var a = DateTime.Now;
        for (int i = 0; i < 5000; i++)
        {
            long N = age * (age + 1) / 2;
            long count = 0;
            for (int j = 2; N!=1; j++)
            {
                int c = 0;
                while (N % j == 0)
                {
                    N /= j;
                    c++;
                }
                count = (count + 1) * (c + 1) - 1;
            }
            double r = ran.Next() % 11;
            r = 1 / (Math.Pow(r, alpha) + 1);
            long R = (long)r + 1;
            if (count >= 500)
            {
                alpha *= 1 + 0.001;
                RR = RR * betta - (1-betta) * R;
                N = age * (age + 1) / 2;
                if (N < mmm)
                {
                    mmm = N;
                    Console.WriteLine(mmm);
                }
            }
            else
            {
                alpha *= 1 - 0.001;
                RR = RR * betta + (1 - betta) * R;
            }
            age += (long)RR;
        }
        var b = DateTime.Now - a;
        Console.WriteLine("R=" + mmm + "  " + b);
        string sss = Console.ReadLine();
    }