B - ランプ列の分割スコア最大化 / Maximizing the Partition Score of a Lamp Sequence 解説 by admin
Claude 4.6 Opus (Thinking)Overview
Given a lamp sequence of \(N\) bits, after performing at most \(K\) operations (removing the leftmost 0 and appending a 1 to the right end), choose a common split position \(p\) for all \(M+1\) lamp sequences, and maximize the sum \(A + B\) of the integer values of the left and right parts.
Analysis
Understanding the Essence of the Operation
The leftmost lamp corresponds to the least significant bit (LSB). The operation is “if the LSB is 0, remove it and append a 1 to the most significant side.”
In terms of bit operations: $\(X \leftarrow (X \gg 1) \mid (1 \ll (N-1))\)$
In other words, this operation removes trailing zeros of \(X\) one by one while packing 1s into the higher-order bits.
Determining the Number of Operations
Let \(t\) be the number of consecutive trailing zeros of \(X\) (if \(X = 0\), then \(t = N\)). The operation stops at the \(t\)-th step when the leftmost bit becomes 1. Therefore, the actual number of operations performed is \(\text{ops} = \min(t, K)\).
Value After Operations
After \(\text{ops}\) operations, the value is: $\(X_{\text{final}} = (X \gg \text{ops}) \mid (((1 \ll \text{ops}) - 1) \ll (N - \text{ops}))\)$
This removes the lower \(\text{ops}\) bits (all zeros) by right-shifting, and fills the upper \(\text{ops}\) bits with 1s.
Choosing the Split Position
When splitting a lamp sequence \(Z\) at position \(p\): - Left part value: \(Z \mathbin{\&} (2^p - 1)\) (lower \(p\) bits) - Right part value: \(Z \gg p\) (upper \(N-p\) bits)
The right part is re-indexed starting from \(2^0\), so it is simply the right-shifted value.
We sum up the left and right values for all \(M+1\) lamp sequences, and find the \(p\) that maximizes the total.
Algorithm
- Find \(t\), the number of consecutive trailing zeros of \(X\), and compute \(\text{ops} = \min(t, K)\)
- Compute \(X_{\text{final}}\) using the formula above
- For each split position \(p\) (\(1 \le p \le N-1\)):
- Compute the total sum of left and right part values for \(X_{\text{final}}\) and all \(Y_j\)
- Output the maximum total sum over all \(p\)
Concrete example (\(N=4, X=12\), i.e., bit sequence 0011):
- The leftmost bit (LSB) is 0, so perform the operation: right shift + set upper bit to 1 → 1011 (there are 2 trailing zeros, so at most 2 operations)
- Splitting at \(p=2\): left 10 (value 2), right 11 (value 3) → total 5
Complexity
- Time complexity: \(O(N \cdot M)\) (\(N-1\) split positions × \(M+1\) lamp sequences)
- Space complexity: \(O(M)\) (storing the input array \(Y\))
With \(N \le 46\) and \(M \le 2 \times 10^5\), this results in approximately \(9 \times 10^6\) operations, which is sufficiently fast.
Implementation Notes
__builtin_ctzllcan efficiently compute the number of trailing zeros, but it is undefined behavior when \(X = 0\), so handle that case separately by setting \(t = N\)When \(\text{ops} = N\) (all bits are 0 and \(K \ge N\)), note the special case where \(X_{\text{final}} = 2^N - 1\) (all bits are 1)
Since \(N \le 46\), all bit operations fit within
long long(64-bit integers)The answer is guaranteed to fit in a
signed 64-bit integer, so there is no concern about overflowSource Code
#include <bits/stdc++.h>
using namespace std;
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
long long N, K, M, X;
cin >> N >> K >> M >> X;
vector<long long> Y(M);
for (int i = 0; i < M; i++) cin >> Y[i];
// Compute trailing zeros of X (as N-bit number)
int t;
if (X == 0) {
t = N;
} else {
t = __builtin_ctzll(X);
}
long long ops = min((long long)t, K);
long long X_final;
if (ops == N) {
X_final = (1LL << N) - 1;
} else {
X_final = (X >> ops) | (((1LL << ops) - 1) << (N - ops));
}
long long ans = 0;
for (int p = 1; p < N; p++) {
long long mask = (1LL << p) - 1;
long long total = (X_final & mask) + (X_final >> p);
for (int j = 0; j < M; j++) {
total += (Y[j] & mask) + (Y[j] >> p);
}
ans = max(ans, total);
}
cout << ans << endl;
return 0;
}
This editorial was generated by claude4.6opus-thinking.
投稿日時:
最終更新: