結果
| 問題 |
No.1743 Permutation Code
|
| ユーザー |
qwewe
|
| 提出日時 | 2025-05-14 13:06:45 |
| 言語 | PyPy3 (7.3.15) |
| 結果 |
MLE
|
| 実行時間 | - |
| コード長 | 9,958 bytes |
| コンパイル時間 | 226 ms |
| コンパイル使用メモリ | 82,380 KB |
| 実行使用メモリ | 821,220 KB |
| 最終ジャッジ日時 | 2025-05-14 13:08:15 |
| 合計ジャッジ時間 | 11,597 ms |
|
ジャッジサーバーID (参考情報) |
judge3 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 7 MLE * 1 -- * 22 |
ソースコード
import sys
# Set a high recursion depth limit for potentially deep searches (large N)
# The problem constraints suggest N could be up to 65535.
# A typical Python default recursion depth is 1000, which is insufficient.
# We need to increase it significantly. 70000 should be safe for N up to 65535.
try:
# Set recursion depth to handle N up to ~70000. Actual required depth depends on N.
sys.setrecursionlimit(70000)
except Exception as e:
# If setting the limit fails (e.g., due to OS restrictions or platform limits),
# print a warning but proceed. The program might crash later with RecursionError.
print(f"Warning: Failed to set recursion depth limit. Error: {e}", file=sys.stderr)
# Memoization dictionary to store results of states (index, used_mask)
# Key: tuple (current index in C, bitmask of used numbers)
# Value: tuple (boolean indicating success, tuple representing permutation suffix if success)
memo = {}
# Input string C
C = ""
# Length of C
C_len = 0
# Estimated upper bound for N. This is used for pruning the search space.
# Numbers larger than N_limit will not be considered.
N_limit = 0
# Maximum length of a binary string segment to consider.
# Determined based on N_limit. A number P_k <= N_limit has at most N_limit.bit_length() bits.
MAX_BIN_LEN = 1 # Initialize, will be updated
def solve():
"""
Main function to read input, estimate parameters, invoke the recursive search,
and print the resulting permutation.
"""
global C, C_len, N_limit, memo, MAX_BIN_LEN
# Read the input string C from standard input
C = sys.stdin.readline().strip()
C_len = len(C)
# Handle edge case: empty input string.
# Based on constraints |C| >= 1, this case might not occur. If it could, decide output.
if C_len == 0:
print() # Output empty line for empty input? Or assume error?
return
# Estimate N roughly to define N_limit for pruning.
# We find the smallest N such that the sum of binary lengths of 1..N is at least |C|.
# This N serves as a lower bound / estimate for the actual N of the permutation.
current_total_len = 0
k = 0 # This k will store the estimated N
temp_N = 0 # Loop variable for estimation
# Iterate N and accumulate total length of binary representations for 1..N
while current_total_len < C_len:
temp_N += 1
# Safety break if N estimate grows excessively large (e.g. > 70000)
# This might indicate an issue with input or extremely large N beyond expectation.
# Max N related to 2^16-1 = 65535 from problem description. 70000 is a safe check bound.
if temp_N > 70000:
print("Error: Estimated N exceeds reasonable limit (70000).", file=sys.stderr)
return # Exit if N seems too large
# k.bit_length() computes floor(log2 k) + 1 efficiently for k >= 1
len_k = temp_N.bit_length()
current_total_len += len_k
# k becomes the first N value where TotalL(N) >= C_len
k = temp_N
# Set N_limit = k + buffer. A small buffer (e.g., 5) accommodates cases where the permutation
# might contain numbers slightly larger than the initial estimate k, potentially due to
# skewness in lengths (more shorter numbers balanced by few very long ones).
N_limit = k + 5
# Ensure N_limit is at least 1 (for edge cases with very short C string)
if N_limit == 0: N_limit = 1
# Update MAX_BIN_LEN based on the determined N_limit.
# The maximum binary length needed is for the number N_limit itself.
if N_limit > 0:
MAX_BIN_LEN = N_limit.bit_length()
else: # If N_limit is 0 (e.g. if C was empty string and logic reached here)
MAX_BIN_LEN = 1 # Minimum length is 1 ('1')
# MAX_BIN_LEN should be at least 1. If N_limit=0 results in bit_length 0, fix it.
if MAX_BIN_LEN == 0: MAX_BIN_LEN = 1
# Clear memoization table for a fresh run for the current test case
memo = {}
# Start the backtracking search from index 0 with an empty mask (no numbers used yet)
found, path_tuple = search(0, 0)
# If a valid permutation path was found
if found:
# Print the permutation elements space-separated
print(*(list(path_tuple)))
else:
# This case should technically not happen based on the problem guarantee
# that a solution exists. If it does, it indicates a potential issue:
# logic error, wrong assumptions, or violation of problem guarantee in test data.
print("Error: Solution not found. Problem guarantee might be violated or logic error.", file=sys.stderr)
def search(index, used_mask):
"""
Recursive search function with memoization to find a valid permutation.
Args:
index: The current starting index in the string C to parse the next number from.
used_mask: A bitmask where the i-th bit is set if the number (i+1) has been used.
Returns:
tuple: (bool, tuple)
- bool: True if a valid permutation suffix was found from this state, False otherwise.
- tuple: The suffix of the permutation path if found, otherwise None.
An empty tuple `()` indicates successful termination at the end of C.
"""
# State tuple used as key for memoization
state = (index, used_mask)
# Return memoized result if this state has been visited before
if state in memo:
return memo[state]
# Base Case: Successfully parsed the entire string C
if index == C_len:
# Check if the sequence of numbers found constitutes a valid permutation {1, ..., N}
# Count the number of elements found (number of set bits in the mask)
num_elements = bin(used_mask).count('1')
# If no elements were found (e.g., empty C was input and somehow reached here), invalid.
if num_elements == 0:
return False, None # Return failure
# Determine N = maximum value present in the permutation.
# N is the index of the most significant bit + 1. int.bit_length() gives this.
max_val = used_mask.bit_length()
# Check Condition 1: The number of elements must equal N (the maximum value).
# This ensures the set is dense from 1 to N without gaps.
if num_elements != max_val:
return False, None # Failure: count mismatch max_val implies gaps or count error
# Check Condition 2: The set of numbers must be exactly {1, ..., N}.
# This check is implicitly covered by Condition 1 IF the mask construction is correct.
# Explicit check: The mask must have bits 0 to N-1 set, which is value (1 << N) - 1.
expected_mask_val = (1 << max_val) - 1
if used_mask == expected_mask_val:
# Valid permutation found! Return success and empty tuple path suffix.
return True, ()
else:
# Failure: Mask doesn't match the expected full set {1..N}.
# This indicates some numbers between 1 and N are missing.
return False, None
# Pruning: If current index has somehow exceeded string length, invalid path.
if index > C_len:
return False, None
# Default result indicating failure for this state (will be updated if success found)
res = (False, None)
# Recursive Step: Explore possible next numbers P_k by trying different lengths L
# Iterate L from 1 up to MAX_BIN_LEN (max possible length of binary string for numbers up to N_limit)
for L in range(1, MAX_BIN_LEN + 1):
# Boundary check: ensure substring C[index : index+L] is within the bounds of C
if index + L > C_len:
break # Cannot form substring of length L, stop trying longer lengths
# Extract substring S_k potentially representing the next number P_k
current_num_str = C[index : index+L]
# Optimization: Binary representation of any positive integer must start with '1'.
# If the substring starts with '0', it cannot be a valid binary representation.
if current_num_str[0] == '0':
continue # Skip this length L, try the next length
# Convert the binary string to an integer P_k
P_k = int(current_num_str, 2)
# Pruning: Check if P_k is within the valid range {1..N_limit}.
# P_k must be positive. Check against N_limit as a heuristic upper bound.
# If P_k > N_limit, it's likely too large for the final permutation N.
if P_k == 0 or P_k > N_limit:
continue # P_k outside reasonable range {1..N_limit}, skip this P_k
# Pruning: Check if P_k has already been used in the current path.
# Check the (P_k - 1)-th bit in used_mask. If it's set, P_k is already used.
if (used_mask >> (P_k - 1)) & 1:
continue # Number P_k already used, cannot reuse. Skip this P_k.
# If P_k is valid (within range, starts with '1') and unused, make a recursive call
# Create the new mask by setting the bit corresponding to P_k
new_mask = used_mask | (1 << (P_k - 1))
# Recursive call for the remainder of the string, starting from new index `index + L`
found, path_suffix_tuple = search(index + L, new_mask)
# If the recursive call found a complete valid solution path
if found:
# Construct the result for the current state: success = True, path = (P_k,) + suffix
res = (True, (P_k,) + path_suffix_tuple)
# Since we only need ONE solution, break the loop immediately after finding one.
break
# Store the computed result (success/failure status + path suffix if success) in memo table
memo[state] = res
return res
# Execute the main solver function when the script is run
solve()
qwewe