結果

問題 No.3301 Make Right Triangle
ユーザー kmmtkm
提出日時 2025-10-05 16:30:31
言語 C++23
(gcc 13.3.0 + boost 1.87.0)
結果
WA  
実行時間 -
コード長 10,656 bytes
コンパイル時間 1,191 ms
コンパイル使用メモリ 116,076 KB
実行使用メモリ 20,324 KB
最終ジャッジ日時 2025-10-05 16:30:58
合計ジャッジ時間 5,751 ms
ジャッジサーバーID
(参考情報)
judge3 / judge2
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample -- * 1
other WA * 1 TLE * 1 -- * 7
権限があれば一括ダウンロードができます

ソースコード

diff #

// 自作ライブラリ
// https://github.com/takumi-okamoto/competitive-programming-public/tree/main/mylib

#include <iostream>
#include <cmath>
#include <string>
#include <numeric> // For std::gcd
#include <vector>
#include <sstream>

/*
Original Python Code:
# 自作ライブラリ
# https://github.com/takumi-okamoto/competitive-programming-public/tree/main/mylib

import sys
import math


# sys.setrecursionlimit(10**8)


def debug(*args):
    print(*args, file=sys.stderr)


def solve(l):
    if l in [3, 4, 5]:
        return "3 4 5"

    # a = k(m**2-n**2)
    # b = 2kmn
    # c = k(m**2 + n**2)
    # gcd(m, n) = 1

    m = 1
    while m * m < l:
        # lが素数の場合
        # m ** 2 + n ** 2 = l
        n2 = l - m * m
        n1 = int(n2**0.5)
        for d in [-1, 0, 1]:
            n = n1 + d
            if n * n == n2:
                break
        else:
            n = None

        if n is not None:
            g = math.gcd(m, n)
            k = g**2
            m = m // g
            n = n // g
            if m > n:
                return f"{k*(m**2 - n**2)} {2*k*m*n} {k*(m**2+n**2)}"

        m += 1

    n = 1
    while 2 * n * n <= l:
        if l % (2 * n) == 0:
            m = l // (2 * n)
            if m > n:
                g = math.gcd(m, n)
                m //= g
                n //= g
                k = g * g
                return f"{k*(m**2 - n**2)} {2*k*m*n} {k*(m**2+n**2)}"
        n += 1

    d = 1
    while d * d <= l:
        if l % d == 0:
            if (l // d - d) % 2 == 0:
                n = (l // d - d) // 2
                m = 2 * n + d
                if m > n:
                    g = math.gcd(m, n)
                    m //= g
                    n //= g
                    k = g * g
                    return f"{k*(m**2 - n**2)} {2*k*m*n} {k*(m**2+n**2)}"
        d += 1


def main():
    t = int(input())
    ans = []
    for _ in range(t):
        ans.append(solve(int(input())))
    print(*ans, sep="\n")
    # for abc in ans:
    # 	a, b, c = map(int, abc.split())
    # 	assert a**2 + b**2 == c**2


if __name__ == "__main__":
    main()

*/

// The Python `debug` function printing to stderr is omitted as it is for debugging, not part of the core algorithm.

using namespace std;

// For simplicity and to match the Python usage of integers, we'll use long long for calculations to prevent overflow.
using ll = long long;

/**
 * @brief Translates the Python `solve` function.
 * * The algorithm attempts to find a Pythagorean triple (a, b, c) such that
 * a + b + c = L (represented as `l` in the code). The logic is based on
 * Euclid's formula for generating Pythagorean triples:
 * a = k(m^2 - n^2), b = 2kmn, c = k(m^2 + n^2), where gcd(m, n) = 1 and m > n.
 * The perimeter L is then: L = a + b + c = 2k m (m + n).
 * The code searches for integers m, n, and k that satisfy the equation for a given L.
 * * The three main search loops correspond to different ways of factoring the perimeter L.
 * The time complexity remains the same: dominated by the first loop which runs
 * up to $\sqrt{L}$ iterations, and the second and third loops running up to $\sqrt{L}$.
 * Thus, the complexity is $O(\sqrt{L})$, which is preserved.
 * * @param l The perimeter L of the Pythagorean triple.
 * @return A string with "a b c" of the found triple, or potentially an empty string if no solution is found (though the problem context implies one should exist or the function logic ensures it).
 */
string solve(ll l) {
    // Handle the base case l in [3, 4, 5]
    if (l == 3 || l == 4 || l == 5) {
        return "3 4 5";
    }

    // --- First loop: Based on L = k(m^2 + n^2) - This part seems to be an incorrect interpretation
    // of the perimeter formula in the original Python code's comment, but the logic
    // m^2 + n^2 = l is tested for finding prime-perimeter triples where k=1.
    // The loop searches for an L that is the hypotenuse (c) of a primitive triple (k=1).
    ll m = 1;
    while (m * m < l) {
        // lが素数の場合 (The comment suggests looking for prime L, but the logic applies generally)
        // m ** 2 + n ** 2 = l
        ll n2 = l - m * m;
        if (n2 <= 0) { // Should not happen given m*m < l, but for safety
             m++;
             continue;
        }

        // Equivalent to n1 = int(n2**0.5)
        ll n1 = (ll)round(sqrt((double)n2)); 
        
        ll n = 0; // Initialize n to 0
        bool found_n = false;

        // Equivalent to: for d in [-1, 0, 1]:
        for (ll d = -1; d <= 1; ++d) {
            ll temp_n = n1 + d;
            if (temp_n > 0 && temp_n * temp_n == n2) {
                n = temp_n;
                found_n = true;
                break;
            }
        }

        // Equivalent to: if n is not None: (i.e., if found_n is true and n > 0)
        if (found_n && n > 0) {
            // Check if m and n form a primitive triple component.
            // g = math.gcd(m, n)
            ll g = std::gcd(m, n);
            // k = g**2
            ll k = g * g;
            // m = m // g
            ll m_prime = m / g;
            // n = n // g
            ll n_prime = n / g;
            
            // The original logic uses the modified m and n to calculate the triple,
            // which effectively sets k' = g^2 and uses the *reduced* primitive pair (m', n').
            if (m_prime > n_prime) {
                ll a = k * (m_prime * m_prime - n_prime * n_prime);
                ll b = 2 * k * m_prime * n_prime;
                ll c = k * (m_prime * m_prime + n_prime * n_prime);
                
                // C++ equivalent to f-string formatting
                stringstream ss;
                ss << a << " " << b << " " << c;
                return ss.str();
            }
        }

        m++;
    }

    // --- Second loop: Based on L = 2k m (m + n). Here the code looks for factors 2n such that L/(2n) = m is an integer.
    // This simplifies the perimeter formula for the case where L = 2kmn and m+n is the other factor,
    // or more directly: L is factorized as L = (2n) * m'. The structure suggests the code is
    // effectively testing L = 2n * m for a potential pair (m, n) from Euclid's formula.
    m = 0; // Reset m for this loop
    ll n_l2 = 1; // Used instead of 'n' to avoid re-using the loop variable name from the first loop, but semantically is the 'n' in Euclid's formula.
    while (2 * n_l2 * n_l2 <= l) {
        // If 2n divides l
        if (l % (2 * n_l2) == 0) {
            // m = l // (2 * n)
            m = l / (2 * n_l2);
            
            if (m > n_l2) {
                // g = math.gcd(m, n)
                ll g = std::gcd(m, n_l2);
                ll m_prime = m / g;
                ll n_prime = n_l2 / g;
                ll k = g * g; // k = g * g
                
                // Calculate and return the triple (a, b, c) using the reduced pair (m', n') and k'.
                ll a = k * (m_prime * m_prime - n_prime * n_prime);
                ll b = 2 * k * m_prime * n_prime;
                ll c = k * (m_prime * m_prime + n_prime * n_prime);
                
                // C++ equivalent to f-string formatting
                stringstream ss;
                ss << a << " " << b << " " << c;
                return ss.str();
            }
        }
        n_l2++;
    }

    // --- Third loop: Based on L = 2k m (m + n). Factorizing L as L = d * d' where d = 2k(m+n) and d' = m. No, the Python logic is:
    // L = d * d' where d is a divisor. The code sets:
    // m - n = d' (or d) and m + n = d (or d').
    // Since L = 2k m (m+n), the factorization L = d * d' here is used to find factors d and d' such that
    // d * d' = L, and from there infer m and n.
    // The code assumes that $L$ is decomposed into $L = (m-n) \times (m+n)$ which is incorrect for perimeter,
    // but the logic `(l // d - d) % 2 == 0` is characteristic of factoring $L = d \times d'$ and
    // finding $m, n$ from $d'$ and $d$. Let $A = m^2-n^2 = (m-n)(m+n)$. If $L$ is a side $A$, then:
    // $m-n = d$ and $m+n = l/d$.
    // $n = (l/d - d) / 2$ and $m = n + d$. This is the exact logic used, implying the function
    // *also* attempts to find an $L$ that is a side of the triple, specifically $a = k(m^2-n^2) = L$.
    ll d = 1;
    while (d * d <= l) {
        if (l % d == 0) {
            ll d_prime = l / d;
            
            // Test if d_prime - d is even. This is necessary for $n$ to be an integer.
            // (l // d - d) % 2 == 0
            if ((d_prime - d) % 2 == 0) {
                // n = (l // d - d) // 2
                ll n_l3 = (d_prime - d) / 2;
                // m = 2 * n + d  => m = n + (n+d) -> m = n + l/d - n -> m = l/d - n. No, the Python code is correct:
                // m = n + d' = (l/d - d)/2 + d = (l/d - d + 2d)/2 = (l/d + d)/2.
                // The Python code is m = 2*n + d. If n=(l/d - d)/2, then 2n = l/d - d.
                // m = (l/d - d) + d = l/d. The Python code is equivalent to: m = l / d.
                // Let's stick to the Python's explicit calculation:
                m = 2 * n_l3 + d;
                
                if (m > n_l3) {
                    // g = math.gcd(m, n)
                    ll g = std::gcd(m, n_l3);
                    ll m_prime = m / g;
                    ll n_prime = n_l3 / g;
                    ll k = g * g; // k = g * g
                    
                    // Calculate and return the triple (a, b, c) using the reduced pair (m', n') and k'.
                    ll a = k * (m_prime * m_prime - n_prime * n_prime);
                    ll b = 2 * k * m_prime * n_prime;
                    ll c = k * (m_prime * m_prime + n_prime * n_prime);

                    // C++ equivalent to f-string formatting
                    stringstream ss;
                    ss << a << " " << b << " " << c;
                    return ss.str();
                }
            }
        }
        d++;
    }

    // FAILED: The original Python code does not have an explicit return path if no solution is found in the loops.
    // Based on the problem context of AtCoder, a solution is expected to be found.
    return "FAILED";
}

void main_func() {
    // Standard I/O for AtCoder contests
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    ll t;
    if (!(cin >> t)) return;

    vector<string> ans;
    for (ll i = 0; i < t; ++i) {
        ll l;
        if (!(cin >> l)) break;
        ans.push_back(solve(l));
    }

    // Print all answers separated by newlines
    for (const string& result : ans) {
        cout << result << "\n";
    }
}

int main() {
    main_func();
    return 0;
}
0