結果
問題 |
No.3066 Collecting Coins Speedrun 1
|
ユーザー |
![]() |
提出日時 | 2025-05-14 13:18:13 |
言語 | PyPy3 (7.3.15) |
結果 |
RE
|
実行時間 | - |
コード長 | 6,575 bytes |
コンパイル時間 | 330 ms |
コンパイル使用メモリ | 82,776 KB |
実行使用メモリ | 72,600 KB |
最終ジャッジ日時 | 2025-05-14 13:19:03 |
合計ジャッジ時間 | 3,996 ms |
ジャッジサーバーID (参考情報) |
judge5 / judge2 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | RE * 2 |
other | RE * 32 |
ソースコード
import sys # Increase recursion depth for potentially deep calls in calculate_grundy. # The required depth depends on PRECOMPUTE_LIMIT. A value like 200 should be safe. try: # Increase recursion depth for deep calculations during precomputation. # The actual depth needed depends on the structure of recursive calls. # Since calculate_grundy(L) depends on smaller values, max depth is roughly L. sys.setrecursionlimit(200) except Exception as e: # Some environments might restrict changing recursion depth. # If so, we rely on the default limit. Memoization helps prune redundant calls. # print(f"Could not set recursion depth: {e}", file=sys.stderr) pass # Memoization dictionary stores computed Grundy numbers memo = {} # Periodicity information determined from analyzing the Grundy sequence PERIOD = 68 PERIOD_START_IDX = 34 # Precompute Grundy numbers up to the point where periodicity is established plus one full period length. # This ensures any L >= PERIOD_START_IDX can rely on values within the range [PERIOD_START_IDX, PERIOD_START_IDX + PERIOD - 1] # PRECOMPUTE_LIMIT = PERIOD_START_IDX + PERIOD = 34 + 68 = 102. We compute values G[0]...G[101]. PRECOMPUTE_LIMIT = PERIOD_START_IDX + PERIOD def calculate_grundy(L): """ Calculates the Grundy number for a segment of length L using memoization and periodicity. """ # Base case: segment of length 0 or less has Grundy value 0. if L <= 0: return 0 # Check memo first: if already computed, return stored value. if L in memo: return memo[L] # Apply periodicity for large L values. # If L is large enough such that its equivalent L based on periodicity must fall # within the precomputed range [0, PRECOMPUTE_LIMIT - 1], we compute its value recursively. if L >= PERIOD_START_IDX: # Calculate the equivalent L within the first periodic block # The equivalent index range is [PERIOD_START_IDX, PERIOD_START_IDX + PERIOD - 1] equivalent_L = PERIOD_START_IDX + (L - PERIOD_START_IDX) % PERIOD # If L itself is outside the precomputation range, its value is determined solely by periodicity. # The value for equivalent_L is guaranteed to be in memo after the precomputation loop finishes. if L >= PRECOMPUTE_LIMIT: res = memo[equivalent_L] # Store the result for L as well, potentially optimizing future calls if L is queried again. memo[L] = res return res # If L is within the precomputed range [PERIOD_START_IDX, PRECOMPUTE_LIMIT - 1], # we proceed to compute it normally. The computation might recursively call calculate_grundy # for values potentially determined by periodicity. Memoization handles this efficiently. # Set to store Grundy values of states reachable from L reachable_grundy_values = set() # Consider possible moves based on game rules: # Operation 1: Choose an isolated empty square ('E' surrounded by 'O' or boundaries) and place a sushi plate. # This operation is only possible for a segment of length L=1. # The segment 'E' becomes 'O', which corresponds to a segment of length 0. if L == 1: reachable_grundy_values.add(calculate_grundy(0)) # G(0) = 0 is the Grundy value of the resulting state. # Operation 2: Choose 3 consecutive empty squares ('EEE') and place sashimi plates on 2 adjacent squares. # This operation is possible for segments of length L >= 3. # 'k' represents the 1-based starting index of the 'EEE' block within the segment. k ranges from 1 to L-2. elif L >= 3: for k in range(1, L-2 + 1): # Option 2a: Place plates on squares k and k+1. The state becomes 'OOE'. # This splits the original segment L into two new segments (possibly empty): # Left segment: squares 1 to k-1. Length k-1. # Right segment: squares k+2 to L. Length L - (k+2) + 1 = L - k - 1. # The Grundy value of the resulting state is the XOR sum of the Grundy values of the two new segments. reachable_grundy_values.add(calculate_grundy(k-1) ^ calculate_grundy(L-k-1)) # Option 2b: Place plates on squares k+1 and k+2. The state becomes 'EOO'. # This splits the original segment L into two new segments: # Left segment: squares 1 to k. Length k. # Right segment: squares k+3 to L. Length L - (k+3) + 1 = L - k - 2. # The Grundy value of the resulting state is the XOR sum. reachable_grundy_values.add(calculate_grundy(k) ^ calculate_grundy(L-k-2)) # If L=2 ('EE'), no moves are possible. Reachable set is empty. # Compute the Minimum Excluded value (mex) from the set of reachable Grundy values. mex = 0 while mex in reachable_grundy_values: mex += 1 # Store the computed Grundy value for L in the memoization table. memo[L] = mex return mex # Precompute Grundy numbers up to PRECOMPUTE_LIMIT using iterative approach. # This ensures that all values needed for periodicity calculations are available. memo[0] = 0 for i in range(1, PRECOMPUTE_LIMIT): # calculate_grundy(i) computes and stores G(i) into memo dictionary. # It relies on G(0)...G(i-1) already being computed and stored. calculate_grundy(i) # Main function to read input and determine the winner def solve(): # Read N and K N, K = map(int, sys.stdin.readline().split()) # Read initial sushi plate positions A = [] for _ in range(N): A.append(int(sys.stdin.readline())) # Problem statement guarantees A_1 < A_2 < ... < A_N, so A is already sorted. # Calculate the Nim-sum (XOR sum) of Grundy values for all segments of empty squares nim_sum = 0 # Calculate length of the first segment (from square 1 to A[0]-1) length1 = A[0] - 1 nim_sum ^= calculate_grundy(length1) # Calculate lengths of segments between consecutive sushi plates A[i] and A[i+1] for i in range(N - 1): length_mid = A[i+1] - A[i] - 1 nim_sum ^= calculate_grundy(length_mid) # Calculate length of the last segment (from A[N-1]+1 to K) length_last = K - A[N-1] nim_sum ^= calculate_grundy(length_last) # Determine the winner based on the Nim-sum. # If Nim-sum > 0, the first player (Yes) has a winning strategy. # If Nim-sum = 0, the second player (No) has a winning strategy. if nim_sum > 0: print("Yes") else: print("No") # Execute the main function solve()