結果
| 問題 |
No.2183 LCA on Rational Tree
|
| ユーザー |
qwewe
|
| 提出日時 | 2025-05-14 13:19:23 |
| 言語 | PyPy3 (7.3.15) |
| 結果 |
TLE
|
| 実行時間 | - |
| コード長 | 4,125 bytes |
| コンパイル時間 | 437 ms |
| コンパイル使用メモリ | 82,568 KB |
| 実行使用メモリ | 439,348 KB |
| 最終ジャッジ日時 | 2025-05-14 13:20:39 |
| 合計ジャッジ時間 | 6,896 ms |
|
ジャッジサーバーID (参考情報) |
judge3 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | TLE * 1 -- * 5 |
ソースコード
import math
import sys
# Function to compute the greatest common divisor (GCD) efficiently.
# Using math.gcd is generally fast as it's likely implemented in C.
def gcd(a, b):
"""Computes the greatest common divisor of a and b."""
return math.gcd(a, b)
def solve():
"""Solves a single query for LCA."""
# Read the input fractions p(u)/q(u) and p(v)/q(v)
P = list(map(int, sys.stdin.readline().split()))
pu1, qu1, pv1, qv1 = P[0], P[1], P[2], P[3]
# Dictionary to store the nodes encountered along the path starting from u1.
# Key: tuple (p, q) representing the rational number p/q.
# Value: The number of steps taken from u1 to reach this node. Useful for debugging or potential optimizations, but not strictly needed for finding LCA here.
u_path = {}
# Start tracing the path from u1 = pu1/qu1
curr_p = pu1
curr_q = qu1
# Set a maximum number of steps to prevent excessively long computations or potential infinite loops.
# This value is chosen based on typical competitive programming constraints and problem analysis.
# If path length exceeds this, the solution might Time Limit Exceed or fail on edge cases.
# Based on problem constraints and typical behavior of such structures, 2*10^6 seems reasonable.
MAX_STEPS = 2 * 10**6
# Generate the path starting from u1
count = 0
while count < MAX_STEPS:
# Store the current node (p, q) and its step count (distance from u1)
u_path[(curr_p, curr_q)] = count
# Calculate the next node p'/q' by applying the operation: (p+1)/(q+1) simplified.
next_p_num = curr_p + 1
next_q_num = curr_q + 1
# Find the greatest common divisor of numerator and denominator to simplify the fraction.
common_divisor = gcd(next_p_num, next_q_num)
# Compute the simplified numerator and denominator for the next node.
# Integer division // is used.
next_p = next_p_num // common_divisor
next_q = next_q_num // common_divisor
# Optional check: if the state (p, q) doesn't change, break to avoid potential infinite loop.
# This condition shouldn't be met for valid inputs in the vertex set V defined as 1 <= p < q.
if next_p == curr_p and next_q == curr_q:
break
# Move to the next node
curr_p = next_p
curr_q = next_q
count += 1
# Now, trace the path starting from v1 = pv1/qv1
curr_p = pv1
curr_q = qv1
count = 0
while count < MAX_STEPS:
# Check if the current node (p, q) from v1's path exists in the path generated from u1.
# The `in` check on dictionary keys is O(1) on average.
if (curr_p, curr_q) in u_path:
# If found, this is the first common node encountered, which is the Lowest Common Ancestor (LCA).
# Print its numerator and denominator.
print(f"{curr_p} {curr_q}")
# Return after finding the LCA for this query.
return
# Calculate the next node in the path from v1
next_p_num = curr_p + 1
next_q_num = curr_q + 1
common_divisor = gcd(next_p_num, next_q_num)
next_p = next_p_num // common_divisor
next_q = next_q_num // common_divisor
# Optional check: state doesn't change
if next_p == curr_p and next_q == curr_q:
break
# Move to the next node
curr_p = next_p
curr_q = next_q
count += 1
# If this point is reached, it means the LCA was not found within MAX_STEPS.
# This could happen if MAX_STEPS is too small for some test cases, or if there's an issue
# with the understanding of the problem structure (e.g., paths diverge indefinitely or cycle differently).
# For the contest setting, it's usually assumed that a solution exists within reasonable bounds.
# Read the number of queries from standard input
Q = int(sys.stdin.readline())
# Process each query one by one
for _ in range(Q):
solve()
qwewe