我刚刚完成了Project Euler问题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;
}
我不禁想到有一个只涉及一个循环的解决方案。有人有想法吗?我更喜欢只使用一个循环的答案,但任何比我现有的效率更高的东西都会很好。
答案 0 :(得分:22)
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,直到你找到一个自然数字出来的。
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.
答案 1 :(得分:5)
我强烈建议您阅读http://en.wikipedia.org/wiki/Pythagorean_triple#Generating_a_triple并编写一个能够逐一生成毕达哥拉斯三元组的函数。
不要给太多的剧透,但是还有很多其他的PE问题,这个功能会派上用场。
(我不认为这太过分了,因为PE的部分目的是鼓励人们学习这样的事情。)
答案 2 :(得分:1)
首先,由于a是最小的,你不需要将它计数到num,num / 3就足够了,甚至是num /(2 + sqrt(2))。 第二,有一个和约束
a+b+c=num
a^2+b^2=c^2
我们可以求解这个方程并找到给定a的b和c,它已经满足这个方程式,并且不需要像现在那样检查^ 2 + b ^ 2 = c ^ 2。您只需要检查b和c是否为整数。这是在一个循环中完成的
for (int a = 1; a < num/3; a++)
答案 3 :(得分:1)
运行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
答案 4 :(得分:1)
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;
}
解决方案对三元组使用Euclid's formula,表示任何原始三元组的形式为a = r ^ 2 - s ^ 2,b = 2rs,c = r ^ 2 + s ^ 2.
可以基于s为正且r> 1的事实来添加诸如sqrt(n / 2)&lt; = r&lt; = sqrt(n)的某些限制。第
警告:如果产品很大,您可能需要很长时间
答案 5 :(得分:0)
您说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;
}
答案 6 :(得分:0)
绝对不是最理想的解决方案,但我的第一直觉是使用修改后的3SUM。在Python中,
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
答案 7 :(得分:0)
在第一个给定的等式中,您有三个变量a, b, c
。如果要查找此等式的匹配值,则必须运行3维循环。幸运的是,还有另一个等式a+b+c=N
,其中N
是已知数字。
使用此功能,您可以将尺寸减小到两个,因为如果您知道三个中的两个,则可以计算其余部分。例如,如果您知道a
和b
,则c
等于N - a - b
。
如果你可以减少循环的另一个维度怎么办?如果你摆弄两个给定的方程式就有可能。得到一支笔和纸。一旦获得具有两个变量和一个常数(N)的附加等式,您将能够在O(n)
中获得结果。求解a+b+c=n; a^2+b^2=c^2
两个方程n
,使a
和b
保持不变,求解c
和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);
}
}
:
page.tpl.php