0309 整数扶梯
* * * *
拉格朗日计划
* * * *
整数扶梯

交叉扶梯是一个经典问题,在这一问题中,已知两架长度分别为x和y的梯子,两者相向倚靠在一条狭长水平街道两侧的墙上,两架梯子相交处的高度为h,要求街道的宽度w。



本问题中只考虑以上四个变量均为正整数的情况。例如若$x=70, y=119, h=30$,则可以求得$w=56$。

事实上,若x、y、h均取正整数,且$0 < x < y < 200$,则只有(70, 119, 30)、(74, 182, 21)、(87, 105, 35)、(100, 116, 35)和(119, 175, 40)这五个三元组(x,y,h)能解得为整数的w。

当$0 < x < y < 1000000$时,这样的三元组有多少个?

本题难度:



解答

如图



显然 $$\frac{h}{a}=\frac{w_2}{w}, \quad \frac{h}{b}=\frac{w_1}{w}$$ 两式相加即得 $$\frac{1}{a}+\frac{1}{b}=\frac{1}{h},$$ 即 $$h=\frac{ab}{a+b}$$ 可以猜测此处a,b似应为整数。如此则可以使用欧几里得法生成所有斜边不超过1000000的勾股数组,并将直角边相互保存在字典中。

然后遍历字典,以键值作为w,该键所对应的值列表中任取两个作为a,b检查是否符合要求,最终结果是$210139$。

import itertools,fractions
from collections import defaultdict

N=1000000
g=defaultdict(set)

u=2
while u*u <= N:
    v=1
    while v < u and (u*u+v*v) <= N:
        if fractions.gcd(u,v)==1:
            a=2*u*v
            b=u*u-v*v
            c=u*u+v*v
            k=1
            while k*c < N:
                g[k*a].add(k*b)
                g[k*b].add(k*a)
                k+=1
        v+=1
    u+=1

print sum((a*b)%(a+b)==0 for i in range(1,N) for a,b in itertools.combinations(g[i],2))