使用Project Euler#23优化我的代码

时间:2012-10-20 06:26:26

标签: c

我正在解决项目欧拉的Problem no 23问题。我使用了一个简单的逻辑,我得到了正确的答案,但是运行程序花了很长时间。

有什么方法可以优化我的代码吗?

我首先计算所有数字,它们是2个丰富数字的总和,然后从总数中减去它。

int factorsum(int);
int main()
{
    int i, j, s = 0, t, m;
    for (i = 24; i <= 28123; i++)   //sum of 2abundant nos start from 24
    {
        for (j = 12; j <= i / 2; j++) {
            t = factorsum(j);
            if (t > j) {
                m = i - j;
                t = factorsum(m);
                if (t > m) {
                    s = s + i;
                    break;
                }
            }
        }

    }
    j = 0;
    for (i = 1; i <= 28123; i++)
        j = j + i;
    printf("\n%d", (j - s));
    return 0;
}

int factorsum(int j)        //checking sum of factors
{
    int k, s = 0;
    for (k = 1; k <= (j / 2); k++) {
        if (j % k == 0) {
            s = s + k;
        }
    }
    return s;
}

1 个答案:

答案 0 :(得分:2)

最大的优化是预先计算除数。目前,您正在为每个factorsum(j)重新计算j = 12, ... i。如果计算一次除数和并将它们存储在数组中,那么它将成为快速(O(1))查找而不是O(j/2)计算。

仅此一项就可以将我的盒子上的运行时间从三分半钟减少到一秒钟。

下一个改进是使用更好的策略来计算除数和。您可以使用除数成对出来的事实,而不是检查每个数字是j/2j只检查(d, j/d)(小心)对于完美的正方形,您只能添加一次平方根。

将其降低到0.05秒。

但是如果将总和存储在一个数组中,你可以通过反转逻辑来做得更好,而不是一次考虑一个数√j并找到它的除数,考虑一个除数n和找到它的所有倍数(d)。这样可以减少计算从k*d(或O(limit^1.5)除以O(limit^2))到j/2的除数和所需的时间。 (注意:由于你给出了一个绝对限制,复杂符号在这里并不严格适用,让我们假装你试图找到不是两个数字之和的数字,直到变量O(limit * log limit)。)

这使得它为0.03秒。