项目欧拉5

时间:2011-12-27 13:43:48

标签: c

2520是可以除以1到10之间的每个数字的最小数字,没有任何余数。

从1到20的所有数字均可被整除的最小正数是多少?

我的解决方案:

#include<stdio.h>
int gcd(int m, int n);
int lcm(int a, int b);
int main()
{
    int x=1, i;
    for(i=1; i<20; i++)
    {
        x=lcm(x, i+1);
    }
    printf("The answer is:\t%d", x);
    return 0;
}

int gcd(int m, int n)
{
    while(m!=n)
    {
        if(m>n)
        m=m-n;
        else
        n=n-m;
    }
    return m;
}

int lcm(int a, int b)
{
    return ((a*b)/gcd(a, b));
}

请告诉我哪里错了?它在运行时仅显示空白屏幕。

7 个答案:

答案 0 :(得分:5)

Project Euler上的大多数问题都可以通过三种方式解决:

  • with brute-force
  • 使用一种解决更普遍问题的算法(就像你一样)
  • 智能解决方案最多需要铅笔和纸张

如果您对一个不错的解决方案感兴趣而不是修改代码,请尝试专注于最后一种方法:

诀窍是找到最小的多重素数,使得1到20之间的任何数字都可以表示为某些素数的乘积。

1 = 1      11 = 11
2 = 2      12 = 2*2*3
3 = 3      13 = 13
4 = 2*2    14 = 2*7
5 = 5      15 = 3*5
6 = 2*3    16 = 2*2*2*2
7 = 7      17 = 17
8 = 2*2*2  18 = 2*3*3
9 = 3*3    19 = 19
10 = 2*5   20 = 2*2*5

通过“ORing”1到10之间的数字的素数因子,我们得到1*2*2*2*3*3*5*7,恰好是2520,正如预期的那样。

现在,如果我们从1到20,我们得到1*2*2*2*2*3*3*5*7*11*13*17*19,这确实被Project Euler所接受。

答案 1 :(得分:2)

如果您只应该从本练习中学到一课,请将其理解为:您进行乘法和除法的顺序非常重要

即使数学无关紧要,但在你的课程中通常也很重要。例如,在数学中,(a*b)/gcd(a, b)a/gcd(a, b)*b之间没有区别;在你的程序中,它会在传递和失败之间产生差异。

(P.S。当然你也需要修正逻辑中的错误:你不应该将x乘以lcm)。

修改

要了解订单在此处产生差异的原因,请考虑计算lcm232792560的{​​{1}}。 20可以将232792560整除,因此它是20。但是,当您计算lcm时,会出现溢出;那么你除以232792560*20,但你没有得到20

由于除数为232792560,您可以在乘以gcd(a,b)之前将其除以a,而不会通过整数除法截断结果。这个经验丰富的程序员不假思索地使用的小技巧可以节省你几个小时的调试时间。

答案 2 :(得分:1)

printf()会告诉您,您的代码正在进入无限循环。我在printf()循环中的gcd()中添加了while

    n=n-m;
    printf("m=%d n=%d\n", m, n); 
}   
return m;
对于while(m!=n)

n=14永远不会成立。最后,mn溢出,因为x转到了int类型无法容纳的更高数字!

答案 3 :(得分:1)

错误是x*=lcm(x, i+1);,这是完整的解决方案,

long gcd(long m, long n);
long lcm(long a, long b);

int main()
{
    long x=1;
    for(int i=2; i<=20; i++)
    {
        x=lcm(x,i);
    }
    cout << "The answer is: " << x << endl;
    return 0;
}

long gcd(long a, long b)
{
        return (b==0)?a:gcd(b,a%b);
}

long lcm(long a, long b)
{
    return ((a*b)/gcd(a, b));
}

答案 4 :(得分:0)

n-1应为n;和x = lcm(...)不是x * = lcm(...)。但是我并没有完全看到(远离终端)你的循环被卡住了。

答案 5 :(得分:0)

20的答案是:232792560。

这些是答案适用于长整数的所有数字的所有答案:

1:1
2:2
3:6
4:12
5:60
6:60
7:420
8:840
9:2520
10:2520&lt; ===例如在欧拉P5问题中除以1到10而没有余数
11:27720
12:27720
13:360360
14:360360
15:360360
16:720720
17:12252240
18:12252240
19:232792560
20:232792560&lt; == Euler Prog 5的答案(1到20没有余数
21:232792560
22:232792560
23:5354228880
24:5354228880
25:26771144400
26:26771144400
27:80313433200
28:80313433200
29:2329089562800
30:2329089562800
31:72201776446800
32:144403552893600
33:144403552893600
34:144403552893600
35:144403552893600
36:144403552893600
37:5342931457063200
38:5342931457063200
39:5342931457063200
40:5342931457063200
41:219060189739591200
42:219060189739591200

答案 6 :(得分:0)

完全不需要为此编写任何程序。我的解决方案:

写下所有不大于最高可除数的质数。

对于20:2、3、5、7、11、13、17、19。

然后,如果任何素数平方根都不大于最大可除数(在此示例中为20),则用其平方根替换原始素数。

在此示例中2 * 2> 20、2 * 2 * 2> 20, 2 * 2 * 2 * 2> 20 ,但2 * 2 * 2 * 2 * 2 <20 2 * 2 * 2 * 2 = 16 ,所以新的数字行是:
16、3、5、7、11、13、17、19。

与3:3 * 3> 20相同,但3 * 3 * 3 <20。3* 3 = 9,因此新的数字行:16、9、5、7、11、13、17、19、5 * 5> 20,所以这是最后一行。

将所有数字乘以该行即可得到答案: 16 * 9 * 5 * 7 * 11 * 13 * 17 * 19 = 232,792,560,