絶滅

どうでもいい

Project Euler - Problem 180

何をやりたい?何もやりたくない



Rational zeros of a function of three variables

Problem 180 (日本語訳)

n を整数とし,3 つの関数

f1, n (x, y, z) = xn + 1 + yn + 1 - zn + 1
f2, n (x, y, z) = (xy + yz + zx)(xn - 1 + yn - 1 - zn - 1)
f3, n (x, y, z) = xyz(xn - 2 + yn - 2 - zn - 2)

とその結合

fn (x, y, z) = f1, n (x, y, z) + f2, n (x, y, z) - f3, n (x, y, z)

について考える.
x, y, z が全て a / b (0 < a < b ≦ k) の形の有理数で,かつ少なくとも 1 つの n に対して fn (x, y, z) = 0 が成立するとき,(x, y, z) をオーダー k の golden triple と呼ぶことにする.

s(x, y, z) = x + y + z とする.
全てのオーダー 35 の golden triple に対して,区別可能な全ての s(x, y, z) の総和を t = u / v とする.
ただし s(x, y, z) および t は既約分数とする.

u + v を求めよ.

fn (x, y, z) = … = (x + y + z)(xn + yn - zn) = 0

⇔ xn + yn = zn

オッ

x = ax / bx , y = ay / by , z = az / bz とおけば,

  • (axbybz)n + (bxaybz)n = (bxbyaz)n (n > 0)
  • (bxayaz)-n + (axbyaz)-n = (axaybz)-n (n < 0)

余白が狭い感じの定理により n = ±1, ±2 に限定される.n は整数なので負の場合も含むのがいやらしい.


C++ でやると通分時のオーバーフローによって死ぬので python でやった.

k = 35 なので 6 重ループを回していけるかと思ったがだいぶ遅かった (C++ なら問題なく終わる).

最終的に分母 35 以下の既約分数で 1 より小さいものの集合をつくり,x と y の対称性を利用して範囲を削ることでどうにか 56 秒ほどに収まった.

C++ の速さと python の便利さをいいとこ取りしたいが……

import math
from fractions import Fraction

def GCD(m, n):
    k = 1
    while k != 0:
        k = m % n
        m = n
        n = k
    return m

def PE0180():
    k = 35
    fracs = set()
    for a in range(1, k):
        for b in range(a + 1, k + 1):
            fracs.add(Fraction(a, b))
    l = list(fracs)
    s = set()
    for x in range(len(l)):
        for y in range(x, len(l)):
            for z in range(len(l)):
                ax = l[x].numerator
                bx = l[x].denominator
                ay = l[y].numerator
                by = l[y].denominator
                az = l[z].numerator
                bz = l[z].denominator
                p0 = ax * by * bz
                p1 = bx * ay * bz
                p2 = bx * by * az
                q0 = bx * ay * az
                q1 = ax * by * az
                q2 = ax * ay * bz
                if p0 + p1 == p2 or q0 + q1 == q2 or p0 * p0 + p1 * p1 == p2 * p2 or q0 * q0 + q1 * q1 == q2 * q2:
                    s.add(l[x] + l[y] + l[z])
    ans = sum(s)
    print(ans.denominator + ans.numerator)


PE0180()