142. 完全平方数集合(Perfect Square Collection)
求使得\(x + y + z\)最小的正整数\(x > y > z > 0\),其中\(x + y\)、\(x - y\)、\(x + z\)、\(x - z\)、\(y + z\)、\(y - z\)六个表达式全部为完全平方数(即某整数的平方)。
一、数学背景
设六个完全平方数分别为:
由这些关系可以推导出\(x, y, z\)用\(a, b, c, d, e, f\)的表达式:
从\((x, y)\)的关系:
从\((x, z)\)的关系:
从\((y, z)\)的关系:
由此得到三个核心等式:
所有六个平方数\(a^2, b^2, c^2, d^2, e^2, f^2\)必须满足相同的奇偶性约束(\(a\)与\(b\)同奇偶、\(c\)与\(d\)同奇偶、\(e\)与\(f\)同奇偶),以保证\(x, y, z\)为整数。
目标函数:
二、算法设计
采用枚举\(e, f\)的策略:
步骤1:枚举\((e, f)\)。 \(e\)和\(f\)必须同奇偶,且\(e > f > 0\)。对于每一对\((e, f)\)计算:
步骤2:从\(y\)求\((a, b)\)。 由\(2y = a^2 - b^2 = (a-b)(a+b)\),令\(u = a-b, v = a+b\),则\(u \cdot v = 2y\)。枚举\(2y\)的所有因子对\((u, v)\),满足\(u < v\)且\(u, v\)同奇偶(保证\(a, b\)为整数):
步骤3:验证\((c, d)\)。 由前面的推导:
检查\(c^2\)和\(d^2\)是否均为完全平方数,且\(c > d\)。
步骤4:返回最小和。 按\(e\)递增的顺序搜索,第一个满足所有条件的解即对应最小的\(x + y + z\)(因为\(x + y + z = a^2 + z\),而\(a^2\)主要由\(e\)的大小决定)。
三、复杂度分析
- 时间复杂度:主要取决于需要尝试的\(e\)值范围。对于本题,答案出现在\(e \approx 90\)附近,因子分解\(2y\)的代价可以忽略
- 空间复杂度:\(O(1)\),不需要额外数组
- 实测运行时间约3.6秒
四、代码实现与说明
#!/usr/bin/env python3
"""
Project Euler Problem 142: Perfect Square Collection
"""
import math
import time
def is_square(n):
"""Check if n is a perfect square."""
if n < 0:
return False
r = int(math.isqrt(n))
return r * r == n
is_square函数
- 检查\(n\)是否为完全平方数
- 使用
math.isqrt(Python 3.8+)快速计算整数平方根 - 比较\(r^2\)与原值\(n\)是否相等
def solve():
e = 2
while True:
# e and f must have same parity for y,z to be integers
for f in range(e % 2 + 2, e, 2):
y = (e * e + f * f) // 2
z = (e * e - f * f) // 2
if z <= 0:
break
# Given y, find a such that a^2 - b^2 = 2y
# 2y = (a-b)(a+b) = u * v where u < v, u*v = 2y
two_y = 2 * y
# Find factors of 2y
u = 1
while u * u <= two_y:
if two_y % u == 0:
v = two_y // u
# a = (u+v)/2, b = (v-u)/2 must be integers and b > 0
if (u + v) % 2 == 0:
a = (u + v) // 2
b = (v - u) // 2
if b > 0:
# Now check c^2 and d^2
c2 = a * a - y + z
d2 = a * a - y - z
if c2 > 0 and is_square(c2) and d2 > 0 and is_square(d2):
c = int(math.isqrt(c2))
d = int(math.isqrt(d2))
x = (a * a + b * b) // 2
# Verify all conditions
if x > y > z > 0:
if (a > b and c > d and e > f and
a > c and c > e and e > b):
return x + y + z
u += 1
e += 1
solve函数——外层循环
e从2开始递增,对于每个\(e\)遍历所有同奇偶的\(f\)(range(e % 2 + 2, e, 2)确保\(f\)与\(e\)同奇偶且\(f > 0\))- 由\((e, f)\)计算\(y\)和\(z\):\(y = (e^2+f^2)/2\),\(z = (e^2-f^2)/2\)
- 若\(z \le 0\)则跳出内层(随着\(f\)增大\(z\)递减,后续\(f\)只会使\(z\)更小或为负)
solve函数——因子分解与(a,b)求解
- \(2y = (a-b)(a+b)\),令\(u = a-b, v = a+b\),则\(u \cdot v = 2y\)且\(u < v\)
- 枚举\(2y\)的所有因子\(u\)(\(u \le \sqrt{2y}\)),对应\(v = 2y / u\)
- 检查\(u+v\)是否为偶数(保证\(a, b\)为整数)
- 计算\(a = (u+v)/2\),\(b = (v-u)/2\),要求\(b > 0\)
solve函数——验证(c,d)条件
- 由推导公式计算:\(c^2 = a^2 - y + z\),\(d^2 = a^2 - y - z\)
- 检查两者是否均为正完全平方数
- 验证所有大小关系:\(a > c > e > b\)以及\(c > d > 0\)和\(e > f > 0\)
- 所有条件满足时,返回\(x + y + z\)
def main():
start = time.time()
answer = solve()
elapsed = time.time() - start
print(f"Answer: {answer}")
print(f"Time: {elapsed:.3f}s")
if __name__ == "__main__":
main()
main函数
- 调用
solve计算答案并计时输出 - 标准Python程序入口