結果
| 問題 |
No.1743 Permutation Code
|
| ユーザー |
qwewe
|
| 提出日時 | 2025-05-14 13:08:23 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
TLE
|
| 実行時間 | - |
| コード長 | 8,715 bytes |
| コンパイル時間 | 1,241 ms |
| コンパイル使用メモリ | 98,216 KB |
| 実行使用メモリ | 6,272 KB |
| 最終ジャッジ日時 | 2025-05-14 13:10:08 |
| 合計ジャッジ時間 | 11,331 ms |
|
ジャッジサーバーID (参考情報) |
judge1 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 7 TLE * 1 -- * 22 |
ソースコード
#include <iostream>
#include <vector>
#include <string>
#include <cmath>
#include <numeric>
#include <set>
#include <vector>
// For compiler intrinsics used in binLength:
#ifdef _MSC_VER // Check if compiling with MSVC
#include <intrin.h> // Include for _BitScanReverse64
#else
#include <climits> // Include for CHAR_BIT (used with __builtin_clzll)
#endif
using namespace std;
// Global variables
string C; // The concatenated binary string input
long long N; // The size of the permutation (1 to N), determined from L
long long L; // Length of the input string C
vector<long long> P; // Stores the current permutation path being explored during backtracking
set<long long> used_numbers; // Tracks numbers used in the current path using a set for quick lookups
bool solution_found = false;// Flag to stop the backtracking search once the first solution is found
/*
* Calculates the length of the standard binary representation of a positive integer k.
* Uses compiler intrinsics for efficiency. Assumes k > 0.
* For MSVC, uses _BitScanReverse64 to find the index of the most significant bit (MSB). Length = MSB index + 1.
* For GCC/Clang, uses __builtin_clzll to count leading zeros. Length = Total bits - leading zeros.
*/
int binLength(unsigned long long k) {
if (k == 0) return 0; // Base case or error, problem states P_i >= 1
#ifdef _MSC_VER
// MSVC specific intrinsic
if (k == 0) return 0; // _BitScanReverse64 requires non-zero input
unsigned long index;
_BitScanReverse64(&index, k); // Find the 0-based index of the MSB
return (int)index + 1; // Length is index + 1
#else
// GCC/Clang specific intrinsic
if (k == 0) return 0; // __builtin_clzll requires non-zero input
// Calculate length based on number of leading zeros
// sizeof(unsigned long long) * CHAR_BIT gives total bits (usually 64)
return (sizeof(unsigned long long) * CHAR_BIT) - __builtin_clzll(k);
#endif
}
/*
* Recursive backtracking function to find a valid permutation P.
* It explores partitions of the string C starting from `index`.
*/
void solve(int index) {
// If a solution has already been found in another recursive branch, prune this one
if (solution_found) {
return;
}
// Base Case: Successfully parsed the entire string C
if (index == L) {
// Check if exactly N numbers were used (meaning we formed a complete permutation of 1..N)
if (used_numbers.size() == N) {
solution_found = true; // Set flag indicating a solution is found
}
return; // Return from this path
}
// Pruning checks:
// If current index is beyond string length, or already used N items before reaching end
if (index > L || used_numbers.size() >= N) {
return; // Invalid path, backtrack
}
// Pruning: Standard binary representations must start with '1'
if (C[index] == '0') {
return; // Invalid path, cannot start a number with '0', backtrack
}
// Determine the maximum possible length of a binary string for numbers up to N
// This helps prune branches where the length 'l' becomes too large.
int max_len = 0;
if (N > 0) max_len = binLength(N);
unsigned long long current_val_calc = 0; // Variable to store the decimal value of the current substring being considered
// Iterate through possible lengths 'l' for the next number in the permutation
for (int l = 1; index + l <= L; ++l) {
// Pruning: If length 'l' exceeds the max possible length for numbers up to N, stop trying longer lengths
if (l > max_len) {
break;
}
// Calculate the decimal value represented by C[index .. index+l-1] efficiently
// Use bit shift left (multiply by 2) and add the new bit (C[index + l - 1] - '0')
current_val_calc = (current_val_calc << 1) | (C[index + l - 1] - '0');
// Pruning: If the current calculated value already exceeds N, any longer string starting at this index will also represent a value > N.
if (current_val_calc > N) {
break;
}
// Ensure value is positive (problem states P_i >= 1)
if (current_val_calc == 0) continue;
// Critical Check: Verify if the current length 'l' matches the standard binary representation length for 'current_val_calc'
// This ensures we use standard representations (e.g., "1" for 1, not "01") and correct number interpretation.
if (binLength(current_val_calc) == l) {
// Check if the current number 'current_val_calc' has NOT been used yet in this path
// uses set::find for O(log N) lookup on average.
if (used_numbers.find(current_val_calc) == used_numbers.end()) {
// Choose: Add the number to the used set and the permutation path vector
used_numbers.insert(current_val_calc);
P.push_back(current_val_calc);
// Explore: Recursively call 'solve' for the next index position (index + l)
solve(index + l);
// If the recursive call found a solution, stop searching in this branch and return
if (solution_found) {
return;
}
// Backtrack: Remove the number from the used set and path vector (undo the choice)
P.pop_back();
used_numbers.erase(current_val_calc);
}
}
}
}
/*
* Function to calculate f(N) = sum of lengths of binary representations for k=1..N
* Uses the derived formula: MN + M + 1 - 2^M, where M = binLength(N) = floor(log2 N) + 1
* This formula computes the total length of the concatenated string C for a permutation of 1..N.
*/
unsigned long long calculate_f_final_formula(long long k) {
// Base case: f(0) = 0
if (k <= 0) return 0;
unsigned long long uk = k; // Use unsigned long long for calculations
int M = binLength(uk); // M is the number of bits in binary representation of k
unsigned long long K_ull = k; // N as unsigned long long
unsigned long long M_ull = M; // M as unsigned long long
if (M == 0) return 0; // Should not happen for k >= 1
// Calculate 2^M safely using bit shift. Check for M=64 edge case if N could be very large.
// For N <= 65535, M <= 16, so 1ULL << M_ull is safe.
unsigned long long pow2M = (M_ull < 64) ? (1ULL << M_ull) : 0; // Placeholder for M=64, not reachable here
// Apply the formula: MN + M + 1 - 2^M
// Max intermediate M*K approx 16 * 65535 ~ 1M, fits well within unsigned long long.
unsigned long long result = M_ull * K_ull + M_ull + 1 - pow2M;
return result;
}
int main() {
// Optimize C++ standard I/O streams for speed
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cin >> C; // Read the input concatenated binary string C
L = C.length(); // Store its length
// Binary search to find the value N such that f(N) = L
// The search range is [1, 65535] based on problem constraints (max L corresponds to N=2^16-1)
long long low = 1, high = 65535;
long long found_N = -1; // Variable to store the found N
while(low <= high) {
long long mid = low + (high - low) / 2; // Calculate midpoint safely to avoid overflow
if (mid <= 0) { // Ensure mid is positive
low = 1; continue;
}
unsigned long long current_L = calculate_f_final_formula(mid); // Calculate f(mid)
if (current_L == L) { // Found the exact N
found_N = mid;
break; // Exit loop, N found
} else if (current_L < L) { // f(mid) is too small, need larger N -> search in upper half
low = mid + 1;
} else { // current_L > L -> f(mid) is too large, need smaller N -> search in lower half
high = mid - 1;
}
}
N = found_N; // Assign the found value of N
// Check if N was found. Problem guarantees it exists.
if (N == -1) {
// Error case: N not found. Should not happen based on problem guarantees.
return 1; // Indicate error
}
// Initiate the backtracking search starting from index 0 of string C
solve(0);
// Print the resulting permutation P found by the backtracking search
for (int i = 0; i < P.size(); ++i) {
cout << P[i] << (i == P.size() - 1 ? "" : " "); // Print space separated values
}
cout << endl; // Print final newline
return 0; // Indicate successful execution
}
qwewe