以下是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)或更低的效率。如果我只是简单地实现一些已知的解决方案,我不会感到惊讶,但如果我是,我找不到它。想法?
答案 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
毋庸置疑,它远非完美的代码,但它完成了工作。