結果
| 問題 |
No.1931 Fraction 2
|
| コンテスト | |
| ユーザー |
qwewe
|
| 提出日時 | 2025-05-14 13:09:31 |
| 言語 | PyPy3 (7.3.15) |
| 結果 |
TLE
|
| 実行時間 | - |
| コード長 | 9,986 bytes |
| コンパイル時間 | 392 ms |
| コンパイル使用メモリ | 82,100 KB |
| 実行使用メモリ | 104,616 KB |
| 最終ジャッジ日時 | 2025-05-14 13:10:51 |
| 合計ジャッジ時間 | 9,614 ms |
|
ジャッジサーバーID (参考情報) |
judge4 / judge1 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 10 TLE * 1 -- * 25 |
ソースコード
import sys
import math
# Set higher recursion depth for extended_gcd if needed, though iterative is safer
# sys.setrecursionlimit(2000)
# Function to compute greatest common divisor
def gcd(a, b):
"""Computes the greatest common divisor of a and b."""
while b:
a, b = b, a % b
return a
# Function for Extended Euclidean Algorithm
def extended_gcd(a, b):
"""
Computes extended Euclidean Algorithm.
Returns tuple (d, x, y) such that d = gcd(a, b) and ax + by = d.
"""
if a == 0:
return b, 0, 1
d, x1, y1 = extended_gcd(b % a, a)
x = y1 - (b // a) * x1
y = x1
return d, x, y
# Function to compute modular inverse
def modInverse(a, m):
"""
Computes the modular multiplicative inverse of a modulo m.
Raises ValueError if inverse does not exist (i.e., gcd(a, m) != 1).
"""
d, x, y = extended_gcd(a, m)
if d != 1:
raise ValueError(f"Modular inverse does not exist for a={a}, m={m}, gcd={d}")
# Return x mod m, ensuring result is positive
return (x % m + m) % m
# Function for modular exponentiation
def fast_pow(base, power, modulus):
"""
Computes (base^power) % modulus using binary exponentiation.
"""
result = 1
base %= modulus # Ensure base is within modulo range
while power > 0:
if power % 2 == 1:
result = (result * base) % modulus
base = (base * base) % modulus
power //= 2
return result
# --- Sieve and Factorization ---
MAX_VAL = 200001 # Maximum value for A_i, B_i + 1
spf = [i for i in range(MAX_VAL)] # Smallest Prime Factor array
primes = [] # List of primes up to MAX_VAL
def sieve():
"""
Sieve of Eratosthenes to precompute Smallest Prime Factor (SPF) for numbers up to MAX_VAL.
"""
is_prime = [True] * MAX_VAL
is_prime[0] = is_prime[1] = False
for i in range(2, MAX_VAL):
if is_prime[i]:
spf[i] = i
primes.append(i)
# Mark multiples of i as not prime and set their SPF
# Start from i*i to optimize
for multiple in range(i * i, MAX_VAL, i):
if is_prime[multiple]: # Check if SPF hasn't been set yet
is_prime[multiple] = False
spf[multiple] = i
sieve() # Precompute SPF table
def get_prime_factorization(num):
"""
Factorizes a number using the precomputed SPF table.
Returns a dictionary {prime: exponent}.
"""
factors = {}
if num <= 0: return {} # Handle non-positive inputs
if num == 1: return {} # Base case for 1
while num > 1:
p = spf[num]
count = 0
while num > 0 and num % p == 0: # Check divisibility and ensure num remains positive
num //= p
count += 1
if count > 0: # Store the prime factor and its exponent
factors[p] = count
# Optimization: if the remaining number is prime (its SPF is itself)
if num > 1 and spf[num] == num:
factors[num] = factors.get(num, 0) + 1
break # Factorization complete
# Exit loop if num becomes 1
if num == 1: break
return factors
# --- Main Solve Function ---
MOD = 998244353 # The modulus specified in the problem
def solve():
"""
Main logic to solve the fraction sum problem.
"""
N = int(sys.stdin.readline())
A = [] # List of numerators
B = [] # List of denominators
B_factors = [] # List of prime factorizations of denominators
for i in range(N):
line = sys.stdin.readline().split()
ai = int(line[0])
bi = int(line[1])
# Basic validation based on problem constraints
if not (1 <= ai <= 200000): raise ValueError(f"A_i={ai} out of bounds 1..200000")
if not (1 <= bi <= 200000): raise ValueError(f"B_i={bi} out of bounds 1..200000")
A.append(ai)
B.append(bi)
if bi >= MAX_VAL: raise ValueError(f"B_i={bi} exceeds MAX_VAL limit {MAX_VAL-1}")
B_factors.append(get_prime_factorization(bi))
# Compute maximum exponent E_p for each prime p involved in any B_i
max_exponents = {} # {prime: max_exponent}
involved_primes = set() # Set of primes that divide at least one B_i
for factors in B_factors:
for p, exp in factors.items():
involved_primes.add(p)
# Update the maximum exponent seen so far for prime p
if p not in max_exponents or exp > max_exponents[p]:
max_exponents[p] = exp
involved_primes_list = sorted(list(involved_primes)) # Sorted list of primes
K = len(involved_primes_list) # Number of distinct prime factors across all B_i
# Calculate L mod MOD, where L = lcm(B_1, ..., B_N)
L_mod = 1
for p in involved_primes_list:
Ep = max_exponents.get(p, 0)
if Ep > 0: # Only include primes with positive maximum exponent
term = fast_pow(p, Ep, MOD)
L_mod = (L_mod * term) % MOD
# Calculate C mod MOD, where C is the numerator of the sum before reduction
# C = sum(A_i * (L / B_i))
# We compute (L/B_i) mod MOD as (L mod MOD) * (B_i^{-1} mod MOD) mod MOD
C_mod = 0
for i in range(N):
if B[i] == 0: continue # Should not happen based on constraints
# B_i^{-1} mod MOD exists because B_i <= 200000 < MOD and MOD is prime
Bi_inv_mod = fast_pow(B[i], MOD - 2, MOD) # Using Fermat's Little Theorem for prime MOD
term = (A[i] * L_mod) % MOD
term = (term * Bi_inv_mod) % MOD
C_mod = (C_mod + term) % MOD
# Compute G = gcd(C, L). We need its prime factorization G = product(p^gp)
G_mod = 1 # G mod MOD
G_factors = {} # Stores {prime: exponent gp} for G
# For each prime p involved, compute gp = min(Ep, nu_p(C))
# where nu_p(C) is the exponent of p in the prime factorization of C.
for p_idx, p in enumerate(involved_primes_list):
Ep = max_exponents[p] # Maximum exponent of p in any B_i
# Compute C mod p^(Ep+1) to determine nu_p(C) up to Ep
Mp_val = pow(p, Ep + 1) # Exact value of p^(Ep+1)
# Compute L'_p = L / p^Ep = product_{q!=p} q^Eq modulo Mp_val
L_prime_p_mod_Mp = 1
for q_idx, q in enumerate(involved_primes_list):
if q != p:
Eq = max_exponents.get(q, 0)
if Eq > 0:
term = fast_pow(q, Eq, Mp_val)
L_prime_p_mod_Mp = (L_prime_p_mod_Mp * term) % Mp_val
# Calculate C mod Mp_val
C_mod_Mp = 0
for i in range(N):
Bi_p_part_exp = B_factors[i].get(p, 0) # Exponent of p in B_i
# Calculate B'_ip = B[i] / p^e_ip. This is the part of B_i coprime to p.
p_pow_Bi_p_part_exp = pow(p, Bi_p_part_exp)
if B[i] == 0: continue
if p_pow_Bi_p_part_exp == 0: raise ValueError("p^exp resulted in 0") # Impossible for p>=2
B_prime_ip_val = B[i] // p_pow_Bi_p_part_exp
if B_prime_ip_val == 0: continue # Should only happen if B[i]=0 initially
# Calculate (L/B_i) mod Mp_val = (p^(Ep - e_ip) * Z_ip) mod Mp_val
# where Z_ip = L'_p / B'_ip
B_prime_ip_mod_Mp = B_prime_ip_val % Mp_val
if B_prime_ip_mod_Mp == 0:
# This implies gcd(B'_ip, Mp) = Mp != 1. But gcd(B'_ip, p)=1, so gcd(B'_ip, Mp)=1.
# This case should be impossible. Included for robustness / debugging.
raise ValueError(f"Impossible case: B_prime_ip_mod_Mp == 0 for i={i}, p={p}")
# B'_ip is coprime to Mp=p^(Ep+1), so inverse exists
B_prime_ip_inv_mod_Mp = modInverse(B_prime_ip_mod_Mp, Mp_val)
# Z_ip mod Mp = (L'_p mod Mp) * (B'_ip^{-1} mod Mp) mod Mp
Z_ip_mod_Mp = (L_prime_p_mod_Mp * B_prime_ip_inv_mod_Mp) % Mp_val
# Calculate p^(Ep - e_ip) mod Mp
p_power_term = fast_pow(p, Ep - Bi_p_part_exp, Mp_val)
# Calculate A_i * (L/B_i) mod Mp
Ai_mod_Mp = A[i] % Mp_val # Ensure A[i] is taken mod Mp
term_i = (Ai_mod_Mp * p_power_term) % Mp_val
term_i = (term_i * Z_ip_mod_Mp) % Mp_val
C_mod_Mp = (C_mod_Mp + term_i) % Mp_val
# Determine nu_p(C) based on C_mod_Mp
if C_mod_Mp == 0:
# If C = 0 mod p^(Ep+1), then nu_p(C) >= Ep+1
nu_p_C = Ep + 1
else:
# Calculate the exact exponent of p dividing C_mod_Mp
temp_C = C_mod_Mp
nu_p_C = 0
# Keep dividing by p until it's no longer divisible
while temp_C > 0 and temp_C % p == 0:
temp_C //= p
nu_p_C += 1
# gp = min(exponent of p in L, exponent of p in C)
gp = min(Ep, nu_p_C)
G_factors[p] = gp # Store the exponent of p in G
# Accumulate G mod MOD
if gp > 0:
G_mod = (G_mod * fast_pow(p, gp, MOD)) % MOD
# Final computation of c and d modulo MOD
# c = (C / G) mod MOD = (C mod MOD) * (G^{-1} mod MOD) mod MOD
# d = (L / G) mod MOD = product(p^(Ep - gp)) mod MOD
if G_mod == 0:
# G mod MOD = 0 impossible since MOD is prime > max(p)
pass
# G^{-1} mod MOD exists since G is not a multiple of MOD
G_inv_mod = fast_pow(G_mod, MOD - 2, MOD)
final_c = (C_mod * G_inv_mod) % MOD
# Calculate d = L/G mod MOD
final_d = 1
for p in involved_primes_list:
Ep = max_exponents.get(p, 0)
gp = G_factors.get(p, 0)
exp_diff = Ep - gp # Exponent of p in d
if exp_diff > 0:
term = fast_pow(p, exp_diff, MOD)
final_d = (final_d * term) % MOD
# Output the result
print(final_c, final_d)
# --- Execution ---
solve()
qwewe