找到毕达哥拉斯三元组,其中a + b + c = 1000

时间:2010-05-12 10:22:07

标签: c algorithm operators pythagorean

毕达哥拉斯三元组是一组三个自然数,a< b< c,为此, a 2 + b 2 = c 2

例如,3 2 + 4 2 = 9 + 16 = 25 = 5 2

恰好存在一个毕达哥拉斯三重态,其中a + b + c = 1000。 找到产品abc。

来源http://projecteuler.net/index.php?section=problems&id=9

我试过但不知道我的代码出错了。这是我在C中的代码:

#include <math.h>
#include <stdio.h>
#include <conio.h>


void main()
{
    int a=0, b=0, c=0;
    int i;
    for (a = 0; a<=1000; a++)
    {
        for (b = 0; b<=1000; b++)
        {
            for (c = 0; c<=1000; c++)
            {
                if ((a^(2) + b^(2) == c^(2)) && ((a+b+c) ==1000)))
                    printf("a=%d, b=%d, c=%d",a,b,c);
            }
        }
    }
getch();    
}

16 个答案:

答案 0 :(得分:30)

我担心^没有做你认为在C中做的事情。你最好的选择是使用a*a作为整数方块。

答案 1 :(得分:29)

#include <math.h>
#include <stdio.h>

int main()
{
    const int sum = 1000;
    int a;
    for (a = 1; a <= sum/3; a++)
    {
        int b;
        for (b = a + 1; b <= sum/2; b++)
        {
            int c = sum - a - b;
            if ( a*a + b*b == c*c )
               printf("a=%d, b=%d, c=%d\n",a,b,c);
        }
    }
    return 0;
}

解释:

     
  • b = a;
         如果a,b(a <= b)和c是毕达哥拉斯三元组,则      那么b,a(b> = a)和c - 也是解决方案,所以我们只能搜索一个案例  
  • c = 1000 - a - b;      这是问题的一个条件(我们不需要扫描所有可能的'c':只计算它)

答案 2 :(得分:17)

这是使用欧几里德公式(link)的解决方案。

让我们做一些数学: 通常,每个解决方案都将具有

形式
a=k(x²-y²)
b=2kxy
c=k(x²+y²)

其中k,x和y是正整数,y < x和gcd(x,y)= 1(我们将忽略这个条件,这将导致其他解决方案。之后可以丢弃这些条件)

现在,a + b + c =kx²-ky²+ 2kxy +kx²+ky²=2kx²+ 2kxy = 2kx(x + y)= 1000

除以2:kx(x + y)= 500

现在我们设置s = x + y:kxs = 500

现在我们正在寻找kxs = 500的解,其中k,x和s是整数,x < s < 2x。 由于它们全部除以500,它们只能取值1,2,4,5,10,20,25,50,100,125,250,500。有些伪代码用于任意n(它可以是手工完成n = 1000)

If n is odd
  return "no solution"
else
  L = List of divisors of n/2
for x in L
  for s in L
    if x< s <2*x and n/2 is divisible by x*s
      y=s-x
      k=((n/2)/x)/s      
      add (k*(x*x-y*y),2*k*x*y,k*(x*x+y*y)) to list of solutions
sort the triples in the list of solutions
delete solutions appearing twice
return list of solutions

你仍然可以改善这一点:

  • x永远不会大于n / 2
  • 的根
  • s的循环可以从x开始,经过2x后停止(如果订购了列表)

对于n = 1000,程序必须检查x的六个值,并根据实现的细节,最多为y的一个值。这将在您释放按钮之前终止。

答案 3 :(得分:14)

如上所述,^是按位xor,而不是幂。

您也可以删除第三个循环,而是使用 c = 1000-a-b;并稍微优化一下。

伪代码

for a in 1..1000
    for b in a+1..1000
        c=1000-a-b
        print a, b, c if a*a+b*b=c*c

答案 4 :(得分:12)

这个问题有一个非常肮脏但快速的解决方案。给出两个方程式

a * a + b * b = c * c

a + b + c = 1000。

您可以推断出以下关系

a =(1000 * 1000-2000 * b)/(2000-2b)

或在两次简单的数学变换之后,你得到:

a = 1000 *(500-b)/(1000-b)

因为必须是自然数。因此你可以:

for b in range(1, 500):
    if 1000*(500-b) % (1000-b) == 0:
        print b, 1000*(500-b) / (1000-b) 

得到结果200和375。

祝你好运

答案 5 :(得分:6)

#include <stdio.h>

int main() // main always returns int!
{
 int a, b, c;
 for (a = 0; a<=1000; a++)
 {
  for (b = a + 1; b<=1000; b++) // no point starting from 0, otherwise you'll just try the same solution more than once. The condition says a < b < c.
  {
   for (c = b + 1; c<=1000; c++) // same, this ensures a < b < c.
   {
    if (((a*a + b*b == c*c) && ((a+b+c) ==1000))) // ^ is the bitwise xor operator, use multiplication for squaring
     printf("a=%d, b=%d, c=%d",a,b,c);
   }
  }
 }
 return 0;
}

没有对此进行测试,但它应该让你走上正轨。

答案 6 :(得分:6)

来自man pow

POW(3)                                       Linux Programmer's Manual                                      POW(3)

NAME
       pow, powf, powl - power functions

SYNOPSIS
       #include <math.h>

       double pow(double x, double y);
       float powf(float x, float y);
       long double powl(long double x, long double y);

       Link with -lm.

   Feature Test Macro Requirements for glibc (see feature_test_macros(7)):

       powf(), powl(): _BSD_SOURCE || _SVID_SOURCE || _XOPEN_SOURCE >= 600 || _ISOC99_SOURCE; or cc -std=c99

DESCRIPTION
       The pow() function returns the value of x raised to the power of y.

RETURN VALUE
       On success, these functions return the value of x to the power of y.

       If  x  is  a  finite  value less than 0, and y is a finite non-integer, a domain error occurs, and a NaN is
       returned.

       If the result overflows, a range error occurs, and the functions return HUGE_VAL, HUGE_VALF, or  HUGE_VALL,

如你所见,pow正在使用浮点运算,这不太可能给你精确的结果(虽然在这种情况下应该没问题,因为相对较小的整数具有精确的表示;但不依赖对于一般情况)...使用n*n来对整数算术中的数字求平方(同样,在具有强大浮点单位的现代CPU中,浮点数的吞吐量甚至可以更高,但是从整数转换为浮点数CPU周期的成本非常高,所以如果你要处理整数,那就试着坚持整数运算。)

一些伪代码可以帮助您优化算法:

for a from 1 to 998:
    for b from 1 to 999-a:
        c = 1000 - a - b
        if a*a + b*b == c*c:
             print a, b, c

答案 7 :(得分:5)

在C中,^运算符计算按位xor,而不是幂。请改用x*x

答案 8 :(得分:2)

正如其他人提到的,你需要理解^运算符。 此外,您的算法将使用不同顺序的参数a,b和c生成多个等效答案。

答案 9 :(得分:2)

虽然很多人都指出,一旦切换到使用pow,您的代码就能正常运行。如果您有兴趣学习一些适用于CS的数学理论,我建议尝试使用“Euclid公式”实现一个更有效的版本来生成Pythagorean三元组(link)。

答案 10 :(得分:2)

我知道这个问题很老了,每个人都在发布带有3个​​for循环的解决方案,这是不需要的。我通过**equating the formulas**; **a+b+c=1000 and a^2 + b^2 = c^2**

在O(n)中解决了这个问题

所以,进一步解决问题;

a+b = 1000-c

(a+b)^2 = (1000-c)^2

如果我们进一步解决我们推断它;

  

α=((50000-(1000 * B))/(1000-B))。    我们循环“b”,找到“a”。

     

一旦我们有“a”和“b”,我们就会得到“c”。

public long pythagorasTriplet(){
    long a = 0, b=0 , c=0;

    for(long divisor=1; divisor<1000; divisor++){
        if( ((500000-(1000*divisor))%(1000-divisor)) ==0){
            a = (500000 - (1000*divisor))/(1000-divisor);
            b = divisor;
            c = (long)Math.sqrt(a*a + b*b);
            System.out.println("a is " + a + " b is: " + b + " c is : " + c);
            break;
        }
    }
    return a*b*c;
}

答案 11 :(得分:1)

Euclid方法给出周长为m(m + n)= p / 2,其中m> 1。 n和边是m ^ 2 + n ^ 2是斜边,腿是2mn和m ^ 2-n ^ 2.thus m(m + n)= 500快速给出m = 20和n = 5。边是200,375和425.使用欧几里德解决所有pythorean原始问题。

答案 12 :(得分:1)

由于有两个方程(a+b+c = 1000&amp; aˆ2 + bˆ2 = cˆ2)有三个变量,我们可以通过循环遍历一个变量的所有可能值来在线性时间内解决它,然后我们就可以了在恒定时间内解决其他2个变量。

从第一个公式得到b=1000-a-c,如果我们用第二个公式替换b,我们得到c^2 = aˆ2 + (1000-a-c)ˆ2,这会简化为c=(aˆ2 + 500000 - 1000a)/(1000-a)

然后我们循环遍历a的所有可能值,用上面的公式求解c和b,如果条件满足,我们就找到了我们的三元组。

    int n = 1000;

    for (int a = 1; a < n; a++) {
        int c = (a*a + 500000 - 1000*a) / (1000 - a);
        int b = (1000 - a - c);

        if (b > a && c > b && (a * a + b * b) == c * c) {
            return a * b * c;
        }
    }

答案 13 :(得分:0)

我认为这里最好的方法是:

int n = 1000;
unsigned long long b =0;
unsigned long long c =0;
for(int a =1;a<n/3;a++){
    b=((a*a)- (a-n)*(a-n)) /(2*(a-n));
    c=n-a-b;

    if(a*a+b*b==c*c)
        cout<<a<<' '<<b<<' '<<c<<endl;
 }

说明: 我们将引用N和A常量,因此我们不必使用两个循环。 我们可以这样做,因为 c=n-a-b和b = (a^2-(a-n)^2)/(2(a-n)) 我通过求解方程组得到了这些公式:

a+b+c=na^2+b^2=c^2

答案 14 :(得分:0)

func maxProd(sum:Int)->Int{
    var prod = 0
    //    var b = 0
    var c = 0
    let bMin:Int = (sum/4)+1 //b can not be less than sum/4+1 as (a+b) must be greater than c as there will be no triangle if this condition is false and any pythagorus numbers can be represented by a triangle.
    for b in bMin..<sum/2 {
        for a in ((sum/2) - b + 1)..<sum/3{ //as (a+b)>c for a valid triangle
            c = sum - a - b
            let csquare = Int(pow(Double(a), 2) + pow(Double(b), 2))
            if(c*c == csquare){
                let newProd = a*b*c
                if(newProd > prod){
                    prod = newProd
                    print(a,b,c)
                }
            }
        }
    }
    //
    return prod
}

上面的答案已经足够好了,但缺少一条重要的信息 a + b&gt; ç即可。 ;)

将向有问题的人提供更多详情。

答案 15 :(得分:0)

for a in range(1,334):
    for b in range(500, a, -1):
        if a + b < 500:
            break
        c = 1000 - a - b
        if a**2 + b**2 == c**2:
            print(a,b,c)

Oleg的答案进一步优化。 一侧不能大于另一侧的总和。 因此a + b不能小于500。