java 我能使这个函数更有效吗(欧拉项目9)?

vktxenjb  于 2022-12-28  发布在  Java
关注(0)|答案(9)|浏览(110)

我刚刚完成了欧拉计划第9题(警告剧透):

A Pythagorean triplet is a set of three natural numbers, a < b < c, for which,
a^2 + b^2 = c^2

For example, 3^2 + 4^2 = 9 + 16 = 25 = 5^2.

There exists exactly one Pythagorean triplet for which a + b + c = 1000.
Find the product abc.

我的解决方案是:

public static int specPyth(int num)
{
    for (int a = 1; a < num; a++)
        for (int b = 2; b < a; b++)
            {
                if (a*a +b*b == (num-a-b)*(num-a-b))
                    return a*b*(num-a-b); //ans = 31875000 
            }

    return -1;
}

我不禁想到,有一个解决方案只涉及一个循环。有人有想法吗?我更喜欢答案只使用一个循环,但任何比我目前更有效的将是很好的。

9rnv2umw

9rnv2umw1#

if a + b +c = 1000

那么

a + b + sqroot(a² + b²) = 1000

 -> (a² + b²) = (1000 - a - b)²

 -> a² + b² = 1000000 - 2000*(a+b) + a² + 2*a*b + b²

 -> 0 = 1000000 - 2000*(a+b) + 2*a*b

 -> ... (easy basic maths)

 -> a = (500000 - 1000*b) / (1000 - b)

然后你尝试每一个B,直到你找到一个使a成为自然数的b。

public static int specPyth(int num)
    {
        double a;
        for (int b = 1; b < num/2; b++)
        {
            a=(num*num/2 - num*b)/(num - b);

            if (a%1 == 0)
                return (int) (a*b*(num-a-b));
        }   

        return -1;
    }

编辑:B不能大于499,因为c〉b,(b+c)就会大于1000。

x9ybnkn6

x9ybnkn62#

我强烈推荐阅读http://en.wikipedia.org/wiki/Pythagorean_triple#Generating_a_triple并编写一个函数,它将逐个生成勾股三元组。
不是给予太多的剧透,但有一些其他的PE问题,这个函数将派上用场。
(我并不认为这是一种过度的放弃,因为体育课的部分目的就是鼓励人们学习这类知识。)

hmtdttj4

hmtdttj43#

首先,因为a是最小的,所以不需要将其计数到num,num/3就足够了,甚至num/(2+sqrt(2))也足够了。

a+b+c=num
a^2+b^2=c^2

我们可以解这个方程,找到B和c,对于给定的a,它们已经满足这个方程,不需要像现在这样检查a^2+b^2=c^2,你需要做的就是检查b和c是否是整数,这是在一个循环中完成的

for (int a = 1; a < num/3; a++)
kfgdxczn

kfgdxczn4#

运行时间为62毫秒

import time
    s = time.time()
    tag,n=True,1000
    for a in xrange (1,n/2):
        if tag==False:
            break
        for b in xrange (1,n/2):
            if a*a + b*b - (n-a-b)*(n-a-b) ==0:
                print a,b,n-a-b
                print a*b*(n-a-b)
                tag=False
    print time.time() - s
wwwo4jvm

wwwo4jvm5#

C溶液
警告:解答假设GCD(a,B)= 1。它在这里工作,但可能不总是工作。我会在一段时间内修复的解决方案。

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

int main(void)
{
  int n = 1000;         // a + b + c = n
  n /= 2;

  for(int r = (int) sqrt(n / 2); r <= (int) sqrt(n); r++)
  {
    if(n % r == 0)
    {
      int s = (n / r) - r;
      printf("%d %d %d\n", r*r - s*s, 2*r*s, r*r + s*s);
      printf("Product is %d\n", (2*r*s) * (r*r - s*s) * (r*r + s*s));
    }
  }

  return 0;
}

解答使用欧几里得的三元组公式,该公式指出任何本原三元组的形式为a = r^2 - s^2,B = 2 rs,c = r^2 + s^2。
基于s为正且r〉s的事实,可以添加某些限制,如sqrt(n / 2)〈= r〈= sqrt(n)。
警告:如果产品较大,您可能需要long long

ttygqcqt

ttygqcqt6#

这肯定不是最佳的解决方案,但我的第一React是使用修改后的3SUM。

def problem_9(max_value = 1000):
    i = 0
    range_of_values = [n for n in range(1, max_value + 1)]
    while i < max_value - 3:
        j = i + 1
        k = max_value - 1
        while j < k:
            a = range_of_values[i]
            b = range_of_values[j]
            c = range_of_values[k]
            if ((a + b + c) == 1000) and (a*a + b*b == c*c):
                return a*b*c
            elif (a + b + c) < 1000:
                j += 1
            else:
                k -= 1
        i += 1
    return -1
ki1q1bka

ki1q1bka7#

假设a < b < c,那么b一定总是大于a,所以第二个循环的起点可能是b = a + 1;这肯定会导致更少的迭代。

int specPyth(int num)
{
    for (int a = 1; a < num/3; a++)
        for (int b = a + 1; b < num/2; b++)
        {
            int c = num - a - b;
            if (a * a + b * b == c * c)
                return a * b * c; //ans = 31875000 
        }

    return -1;
}
kmynzznz

kmynzznz8#

在第一个方程中,你有三个变量a, b, c。如果你想找到这个方程的匹配值,你必须运行三维循环。幸运的是,还有另一个方程a+b+c=N,其中N是已知数。
如果你知道三个维度中的两个,你就可以计算出剩下的维度,例如,如果你知道abc等于N - a - b
如果你能再减少一个维度呢?如果你摆弄两个给定的方程,这是可能的。拿一支笔和一张纸。一旦你得到了两个变量和一个常数的附加方程(N)、您将能够获取O(n)中的结果。以na为常数,求解两个方程a+b+c=n; a^2+b^2=c^2,并求解bc

public static void main(String[] args) {
    Scanner in = new Scanner(System.in);
    int t = in.nextInt();
    for(int a0 = 0; a0 < t; a0++){
        int n = in.nextInt(); 
        int max=-1;
        int multi=0;
       int b=1,c=1;
        for(int i=1;i<=n;i++)
            {
            if(2*(i-n)!=0)
            b=(2*i*n-(n*n))/(2*(i-n));
            c=n-b-i;
            if( (i*i+b*b==c*c)&& i+b+c==n && b>0 && c>=0 && i+b>c && c+i>b && b+c>i)
                {
                multi=i*b*c;
                if(max<multi)
                    max=multi;

            }
        }
        if(max==-1)
        System.out.println(-1);
        else
            System.out.println(max);

    }
}
pcww981p

pcww981p9#

巨蟒:
在开始编写代码之前,先做一个简单的代数练习。
a^2 + b^2 = c^2
a + b + c = 1000--〉c = 1000-(a + b)
a^2 + b^2 =(1000-(a + b))^2
a = 1000 *(500-b)/(1000-b)
现在是编写代码的时候了。

for b in range(2, 500):
    a = 1000*(500 - b)/(1000 - b)
    if a.is_integer():
        c = 1000 - (a+b)
        print(a, b, c, a*b*c)
        break

相关问题