Project Euler#5解决方案比已知解决方案更有效吗?

时间:2010-09-03 02:57:56

标签: c algorithm

以下是Project Euler problem #5的解决方案:

#include <stdio.h>
#include <stdint.h>

#define N 20

int main( int argc, char* argv[] )
{
   uint64_t r = 1;
   uint64_t i, j;

   for( i = 2; i <= N; ++i )
      if( (j = r%i) )
         r *= ( (i%j) ? i : (i/j) );

   printf( "\n%llu\n", r );

   return 0;
}

效率为O(n)。我查看了包含各种解决方案的官方帖子的几页,但我没有注意到O(n)或更低的效率。如果我只是简单地实现一些已知的解决方案,我不会感到惊讶,但如果我是,我找不到它。想法?

3 个答案:

答案 0 :(得分:6)

问题是,你的算法并不完全正确。例如,对于27,它返回722820898800,而80313433200更小并且也有效(可被2..27整除)。

在你的循环体中,你似乎做Euclid's algorithm的前两步以找到最大公约数。虽然对于小数字而言两个步骤就足够了,但是更大的数字需要更多的操作(这就是使用递归的原因)。

因此,您的解决方案可以像这样修复('gcd'代表最大公约数)

for( i = 2; i <= N; ++i )
    r *= i / gcd(i, r);

答案 1 :(得分:2)

我是用纸/铅笔做的。

查找指定范围内数字的lcm(1, 2, ..., 20)(最少公倍数)。您可以轻松证明您可以将上述解决方案缩减为:

lcm(11, 12, ..., 20)

将其作为阅读的练习;)

答案 2 :(得分:0)

我最初的方法与你的方法非常相似,产生结果需要花费很长时间。 这个人在几秒钟内做到了 我将所有素数乘以1到20(2,3,5,7,11,13,17,19) 这个想法是素数没有GCD,最小的合格数字必须是他们的产品。

acnum=0.0
testnum=9699690
divisor=20.0
while acnum==0.0:    

    if testnum%divisor==0.0:
        divisor-=1.0

        print testnum, divisor
    else:
        testnum+=9699690
        divisor=20.0


    if divisor==1.0:
        acnum=testnum

毋庸置疑,它远非完美的代码,但它完成了工作。