C#三角数字优化

时间:2013-03-11 18:41:50

标签: c# optimization divider

任务是找到一个至少有500个除数的三角形数。

例如28有6个除数:1,2,4,7,14,28

我的代码适用于最多200个除数,但对于500,它会永远运行...

有没有办法优化代码。比如我想过动态优化和memoization,但找不到办法呢?

            int sum = 0;
            int counter = 0;
            int count = 1;

            bool isTrue = true;
            while (isTrue)
            {
                counter = 0;
                sum += count;

                for (int j = 1; j <= sum; j++)
                {
                    if (sum % j == 0)
                    {
                        counter++;
                        if (counter == 500)
                        {
                            isTrue = false;
                            Console.WriteLine("Triangle number: {0}", sum);
                            break;
                        }
                    }
                }
                count++;
            }            
            Console.WriteLine("Number of divisors: {0}", counter);

6 个答案:

答案 0 :(得分:5)

忽略这个数字是三角形数字的事实。如果你能快速解决这个问题:

  • 给出任意数字n,确定它具有的除数
那么显然你可以快速解决欧拉#12。只需列出易于计算的三角形数字,确定每个的除数,并在得到500或更大的结果时停止。

那么如何快速确定除数的数量呢?正如你所发现的那样,当数字变大时,这是很多工作。

这是一个提示。假设您已经拥有素数因子分解。让我们选一个数字,比方说,196.将其分解为素数:

196 = 2 x 2 x 7 x 7

我只能通过看一下196具有九个除数的因子分解来告诉你。怎么样?

因为任何除数为196的形式为:

(1, 2 or 2x2) x (1, 7 or 7x7)

显然有九种可能的组合:

1 x 1
1 x 7
1 x 7 x 7
2 x 1
2 x 7
2 x 7 x 7
2 x 2 x 1
2 x 2 x 7
2 x 2 x 7 x 7

选择另一个号码。 200,让我们说。那是2 x 2 x 2 x 5 x 5.所以有十二的可能性:

1 x 1
1 x 5
1 x 5 x 5
2 x 1
2 x 5
...
2 x 2 x 2 x 5 x 5

看模式?您采用素数分解,按素数对它们进行分组,并计算每组中的数量。然后,为每个数字添加一个并将它们相乘。同样,在200中,素数因子分解中有三个两个和两个五个。每个添加一个:四个三个。将它们相乘:十二。这就是有多少除数。

如果你知道素数分解,你可以很快找到除数的数量。我们已将除数问题简化为更容易解决的问题:您能否弄清楚如何快速生成素数分解?

答案 1 :(得分:2)

这里有一些优化,我会把它扔给你。

最简单的事情是改变

for (int j = 1; j <= sum; j++)
{
    if (sum % j == 0)
    {
        counter++;
        if (counter == 500)
        {
            isTrue = false;
            Console.WriteLine("Triangle number: {0}", sum);
            break;
        }
    }
}

如果你找到了1个除数,你就找到了2个除数,所以将其改为

for (int j = 1; j <= sum; j++)
{
    if (sum % j == 0)
    {
        if(sum/j < j)
            break;
        else if(sum/j == j)
            counter++;
        else
            counter +=2;

        if (counter == 500)
        {
            isTrue = false;
            Console.WriteLine("Triangle number: {0}", sum);
            break;
        }
    }
}

这将大大减少运行时间,但仍需要很长时间。


您可以做的另一个优化是不开始检查表单sum,但计算具有500个除数的最小数字。

然后你可以在那之后找到最大的三角形数字,并从那里开始。


如果你能找到关于这个问题的本质的特别之处,那么你可以减少运行时间。

答案 2 :(得分:1)

数字的除数是主要因子加上1的幂的乘积。例如:28 = 2^2*7^1,因此除数的数量为(2+1)*(1+1) = 6

这意味着,如果你想要多个除数与数字的大小相比,你不希望任何一个素数过于频繁。换句话说:至少有500个除数的最小三角数可能是小素数的小权力的乘积。

因此,不是检查每个数字以查看它是否划分三角形数字,而是查看最小素数的列表,并查看每个数字在素数因子分解中出现的频率。然后使用上面的公式计算除数的数量。

答案 3 :(得分:0)

采取以下步骤:

1。)计算第一个log(2,499)素数(不是500,因为如果我错了,因为它不是素数,因为它只有一个除数,因此1被算作除数)。那里有很多解决方案,但你抓住了我的漂移。

2。)三角形数字的形式为n *(n + 1)/ 2,因为 1 + 2 + ... + 100 =(1 + 100)+(2 + 99)+ ... +(50 + 51)= 101 * 50 = 101 * 100/2 = 5050(当Cauchy解决它时是一个八岁男孩,老师用这个任务惩罚他。)

1 + ... + n =(1 + n)+(2 + n - 1)+ ... = n *(n + 1)/ 2.

3。)S = prod(第一个log(2,499)素数)

4。)求解n *(n + 1)/ 2 = S的等式并计算其上限。你将有一个整数,我们称之为m。

5。)

while (not(found))
    found = isCorrect(m)
    if (not(found)) then
        m = m + 1
    end if
end while
return m

然后你去。如果我能够帮助你,请告诉我。

答案 4 :(得分:0)

正如@EricLippert和@LajosArpad所提到的,关键的想法是仅迭代triangle numbers。您可以使用以下公式计算它们:

  

T(n)= n *(n + 1)/ 2

以下是JSFiddle,您可能会觉得有帮助。

function generateTriangleNumber(n) {
    return (n * (n + 1)) / 2;
}

function findTriangleNumberWithOver500Divisors() {
    var nextTriangleNum;
    var sqrt;
    for (i = 2;; i++) {
        var factors = [];
        factors[0] = 1;
        nextTriangleNum = generateTriangleNumber(i);
        sqrt = Math.pow(nextTriangleNum, 0.5);
        sqrt = Math.floor(sqrt);
        var j;
        for (j = 2; j <= sqrt; j++) {
            if (nextTriangleNum % j == 0) {
                var quotient = nextTriangleNum / j;
                factors[factors.length] = j;
                factors[factors.length] = quotient;
            }
        }
        factors[factors.length] = nextTriangleNum;
        if (factors.length > 500) {
            break;
        }
    }
    console.log(nextTriangleNum);
}

答案 5 :(得分:-1)

顺便提一下,divisors of triangular number搜索查询的第一个Google结果就是这样:)

Project Euler 12: Triangle Number with 500 Divisors

看看它是否有帮助。

编辑:该文章中的文字:

  

超过500位的第一个三角形数字是:76576500解决方案   花了1毫秒