結果

問題 No.1743 Permutation Code
ユーザー qwewe
提出日時 2025-05-14 13:05:05
言語 C++17
(gcc 13.3.0 + boost 1.87.0)
結果
TLE  
実行時間 -
コード長 8,020 bytes
コンパイル時間 641 ms
コンパイル使用メモリ 83,688 KB
実行使用メモリ 16,064 KB
最終ジャッジ日時 2025-05-14 13:07:01
合計ジャッジ時間 10,983 ms
ジャッジサーバーID
(参考情報)
judge5 / judge4
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
other AC * 7 TLE * 1 -- * 22
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <iostream>
#include <vector>
#include <string>
#include <numeric>
#include <algorithm>
#include <string_view> // Use string_view for efficiency to avoid copying substrings

// Global variables to store the state accessible by the recursive function
std::string C; // The concatenated binary string input
int N; // The size of the permutation (numbers 1 to N)
std::vector<bool> available; // Tracks which numbers from 1 to N are still available to be used
std::vector<int> result_permutation; // Stores the permutation being built / the final result
int max_len_N; // The maximum possible bit length for any number up to N

/**
 * @brief Converts a binary string (represented by string_view) to its decimal integer value.
 * 
 * @param bin_sv A string_view representing the binary string. Must contain only '0' and '1'.
 * @return The decimal value of the binary string.
 */
long long binToDecView(std::string_view bin_sv) {
    long long dec = 0;
    // Efficient conversion using bit shifts.
    // Assumes input contains only '0' and '1'.
    // The maximum value N=65535 (16 bits) fits well within long long (64 bits).
    for (char c : bin_sv) {
        dec = (dec << 1) | (c - '0');
    }
    return dec;
}

/**
 * @brief The recursive backtracking function to find a valid permutation.
 * 
 * @param index The current starting index in the concatenated string C to parse from.
 * @return True if a valid permutation is found from this state, False otherwise.
 */
bool solve(int index) {
    // Base case: If we have successfully parsed the entire string C
    if (index == C.length()) {
        // A valid partition covers the entire string C.
        // We also need to ensure exactly N numbers were used.
        // This check confirms we formed a complete permutation of 1..N.
        return result_permutation.size() == N; 
    }

    // Determine the maximum length for the next binary string segment we can try.
    // It cannot be longer than the remaining part of C, nor longer than the maximum
    // bit length required for any number up to N.
    int current_max_len = std::min(max_len_N, (int)C.length() - index);

    // Iterate through all possible lengths `l` for the next number's binary representation.
    for (int l = 1; l <= current_max_len; ++l) {
        // Extract the substring of length `l` starting at `index`.
        // Use string_view to avoid expensive string copying.
        std::string_view sub = std::string_view(C).substr(index, l);
        
        // The binary representation of any integer P_i >= 1 must start with '1'
        // (no leading zeros allowed). Check this condition.
        if (sub[0] == '0') continue; // Skip if it starts with '0'

        // Convert the binary substring `sub` to its integer value `k`.
        long long k_ll = binToDecView(sub);
        
        // Check if the obtained integer `k` is valid for the permutation:
        // 1. Must be positive (i.e., >= 1).
        // 2. Must not exceed N (the upper bound of the permutation range).
        if (k_ll <= 0 || k_ll > N) { 
             continue; // k is outside the valid range {1, ..., N}
        }
        int k = (int)k_ll; // Safe to cast to int because 1 <= k_ll <= N <= 65535 fits in standard int.

        // Check if the number `k` is available (i.e., hasn't been used yet in the permutation)
        if (available[k]) {
            // Try including k in the permutation
            available[k] = false; // Mark k as used
            result_permutation.push_back(k); // Add k to the current sequence being built

            // Recursively call solve for the remainder of the string C, starting after the current segment.
            if (solve(index + l)) {
                // If the recursive call finds a solution, it means we found a valid complete permutation.
                // Propagate true up the call stack.
                return true; 
            }

            // Backtrack: If the choice of `k` did not lead to a solution, undo the choice.
            result_permutation.pop_back(); // Remove k from the sequence
            available[k] = true; // Mark k as available again, allowing other paths to use it.
        }
    }

    // If we tried all possible lengths `l` from the current `index` and none led to a solution,
    // then this path is invalid. Return false.
    return false; 
}

/**
 * @brief Calculates the number of bits in the binary representation of integer k (without leading zeros).
 * Equivalent to floor(log2(k)) + 1 for k > 0.
 * 
 * @param k The positive integer.
 * @return The number of bits required. Returns 0 for k <= 0.
 */
long long integer_bit_length(int k) {
    if (k <= 0) return 0; // Bit length is defined for positive integers.
    
    // Calculate bit length using integer operations (safer than float log2).
    long long len = 0;
    unsigned int tempK = k; // Use unsigned type for right bit shifts to avoid potential sign extension issues.
    while (tempK > 0) {
        tempK >>= 1; // Right shift by 1 is equivalent to dividing by 2.
        len++;
    }
    // Example: k=1 (0b1) -> len=1. k=2 (0b10) -> len=2. k=3 (0b11) -> len=2. k=4 (0b100) -> len=3.
    // This correctly computes the number of bits.
    return len;
}


int main() {
    // Use fast I/O operations for performance critical competitive programming tasks.
    std::ios_base::sync_with_stdio(false);
    std::cin.tie(NULL);

    std::cin >> C; // Read the concatenated binary string input C.

    long long target_len = C.length(); // The required total length of concatenated binary strings.
    // Problem constraints state |C| >= 1, so target_len will be at least 1.

    // Determine the value of N by summing the bit lengths of integers 1, 2, ..., N
    // until the total length matches target_len.
    long long current_len = 0;
    N = 0; // Start counting N from 1.
    while(current_len < target_len) {
        N++;
        // Basic check to prevent infinite loop or overflow if N becomes unexpectedly large.
        // Maximum N is 65535 based on max |C|, safely within int range.
        if (N <= 0) return 1; // Error state check.
        
        current_len += integer_bit_length(N); // Add the bit length of the current number N.
    }

    // Verify that the calculated total length matches the input string length.
    // The problem guarantees that such an N exists and a permutation can be formed.
    if (current_len != target_len) {
         // This case indicates an inconsistency, potentially a bug or misinterpretation.
         // According to the problem, this should not happen.
         return 1; // Exit with error code.
     }
     
    // Calculate the maximum bit length required for any number in the range 1..N.
    // This is simply the bit length of N itself.
    max_len_N = integer_bit_length(N); 
    
    // Initialize data structures needed for the backtracking search.
    // `available` vector tracks usage of numbers 1 to N. Size N+1 for 1-based indexing.
    available.resize(N + 1, true); 
    available[0] = false; // Index 0 is unused.
    
    // `result_permutation` will store the found sequence. Reserve space for N elements
    // to potentially improve performance by avoiding reallocations during push_back.
    result_permutation.reserve(N);

    // Start the backtracking search from the beginning of the string C (index 0).
    if (!solve(0)) {
         // If solve(0) returns false, it means no solution was found.
         // This contradicts the problem statement's guarantee that a solution exists.
         // Indicates a potential issue with the logic or implementation.
         return 1; // Exit with error code.
    }

    // Print the found permutation elements, separated by spaces.
    for (int i = 0; i < result_permutation.size(); ++i) {
        std::cout << result_permutation[i] << (i == result_permutation.size() - 1 ? "" : " ");
    }
    std::cout << std::endl; // Ensure the output ends with a newline character.

    return 0; // Indicate successful execution.
}
0