結果
問題 |
No.2045 Two Reflections
|
ユーザー |
![]() |
提出日時 | 2025-05-14 13:04:06 |
言語 | PyPy3 (7.3.15) |
結果 |
AC
|
実行時間 | 66 ms / 2,000 ms |
コード長 | 5,853 bytes |
コンパイル時間 | 173 ms |
コンパイル使用メモリ | 82,284 KB |
実行使用メモリ | 79,480 KB |
最終ジャッジ日時 | 2025-05-14 13:05:50 |
合計ジャッジ時間 | 2,886 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge3 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 3 |
other | AC * 27 |
ソースコード
import sys import math # Set higher recursion depth for safety, although iterative approach is used. # sys.setrecursionlimit(200000) # Probably not needed with iterative approach # Use math.gcd for potentially better performance as it's implemented in C. gcd = math.gcd # Function to compute least common multiple (LCM) of two numbers. def lcm(a, b): # If either number is 0, LCM is 0. if a == 0 or b == 0: return 0 # Optimization: LCM with 1 is the other number. if a == 1: return b if b == 1: return a # Calculate LCM using the formula: lcm(a, b) = |a * b| / gcd(a, b) # Use integer division // g = gcd(a, b) # Python's arbitrary precision integers handle large numbers, so a * b won't overflow. # The form (a // g) * b is sometimes used to potentially keep intermediate numbers smaller, # but it's not strictly necessary for correctness in Python. return (a * b) // g def solve(): # Read input N, p, q N, p, q = map(int, sys.stdin.readline().split()) # Define the modulus MOD = 998244353 # Handle special cases where the group generated by R_p and R'_q is small (size 1 or 2) # Case 1: Both operations are Identity. This happens if p=1 and q=1. # The group is {Id}, size is 1. if p == 1 and q == 1: print(1) return # Case 2: One operation is Identity, the other is not. # If p=1, R_p = Id. The group generated is {Id, R'_q}. # Since q != 1 (covered by Case 1), R'_q is not Id (requires q > 1, which is true unless N=1, # but N=1 implies p=1, q=1). Size is 2. if p == 1: print(2) return # If q=1, R'_q = Id. The group generated is {Id, R_p}. # Since p != 1 (covered by Case 1), R_p is not Id. Size is 2. if q == 1: print(2) return # Case 3: The two operations are identical and non-Identity. # This happens only if p=N and q=N. # R_p = R_N (reverses 1..N), R'_q = R_N (reverses 1..N). # The group generated is {Id, R_N}. Size is 2. # Note: This requires N > 1, otherwise p=1, q=1 falls into Case 1. # If N > 1, then p=N > 1 and q=N > 1, so R_N is not Identity. if p == N and q == N: print(2) return # General case: p > 1, q > 1, and R_p != R'_q. # The group generated by R_p and R'_q is a dihedral group of order 2k, # where k is the order of the permutation P = R_p * R'_q. # We need to find k by computing the LCM of cycle lengths of P. # Function to compute P(i) = R_p(R'_q(i)) def compute_P(i): # Apply R'_q: Reflects indices in the range [N-q+1, N] # The reflection maps an index j in the range to (N-q+1) + (N - j). # Simplified: 2*N - q + 1 - j i_prime = i if N - q + 1 <= i <= N: i_prime = 2 * N - q + 1 - i # Apply R_p: Reflects indices in the range [1, p] # The reflection maps an index k in the range to 1 + (p - k). # Simplified: p + 1 - k i_final = i_prime if 1 <= i_prime <= p: i_final = p + 1 - i_prime return i_final # Use a boolean list to keep track of visited indices. Size N+1 for 1-based indexing. visited = [False] * (N + 1) # Variable to store the least common multiple (LCM) of cycle lengths found so far. Initialize to 1. current_lcm = 1 # Iterate through all indices from 1 to N to find cycles for i in range(1, N + 1): # If index i has already been visited (part of a previous cycle), skip it. if not visited[i]: curr = i # Use a dictionary to keep track of nodes encountered in the current path trace # and the step count at which they were first encountered. path_indices = {} steps = 0 # Trace the path starting from i until we encounter a node that has been visited before. while not visited[curr]: visited[curr] = True # Mark the current node as visited path_indices[curr] = steps # Record the step count for this node curr = compute_P(curr) # Move to the next node in the permutation sequence steps += 1 # After the loop, `curr` is the first node encountered that was already visited. # We need to check if `curr` was visited during *this* trace run (meaning we found a cycle) # or if it was visited in a *previous* trace run (meaning this path leads into an existing cycle). if curr in path_indices: # `curr` is in path_indices, so it was visited during this trace run. A cycle is found. # The cycle starts at the node `curr`. first_occurrence_idx = path_indices[curr] # Step count when `curr` was first visited in this path cycle_len = steps - first_occurrence_idx # Length of the cycle # Update the overall LCM with the length of this new cycle. # A cycle must have length > 0. Check just in case. if cycle_len > 0: current_lcm = lcm(current_lcm, cycle_len) # else: `curr` was not in path_indices. This means it was visited in a previous trace run. # The path starting from `i` leads into a cycle that has already been processed. # No new cycle found, so no update to LCM is needed from this path trace. # The total number of distinct sequences is the size of the group, which is 2 * k. # k is the order of P, which is the calculated `current_lcm`. # Compute the final answer modulo MOD. result = (2 * current_lcm) % MOD print(result) # Call the solve function to run the logic solve()