C - 暗号変換と補正 / Cipher Conversion and Correction Editorial by admin
gpt-5.5-highOverview
For each split position \(k\), we determine whether there exists a monotonically non-increasing correction sequence \(D\) that satisfies the conditions for the XOR-transformed values \(A_i\).
The existence check for the correction sequence can be done efficiently by considering the range of possible values for each \(D_i\) and greedily determining them from left to right.
Analysis
Let’s fix the split position \(k\).
Let \(X_L\) be the XOR of the first half and \(X_R\) be the XOR of the second half. Then the transformed values \(A_i\) are as follows:
- For \(1 \le i \le k\): \(A_i = S_i \oplus X_R\)
- For \(k+1 \le i \le N\): \(A_i = S_i \oplus X_L\)
Here, \(S_i\) is the ASCII code of the character.
Next, let’s consider the conditions that the correction value \(D_i\) must satisfy for a given \(A_i\).
From the problem’s conditions:
\[ 97 \le A_i + D_i \le 122 \]
and
\[ D_i \ge 0 \]
Therefore, the range of possible values for \(D_i\) is:
\[ \max(0, 97 - A_i) \le D_i \le 122 - A_i \]
Let the lower bound be \(L_i\) and the upper bound be \(U_i\).
In other words, the problem becomes: can we choose values satisfying
\[ D_i \in [L_i, U_i] \]
for each position \(i\), while also satisfying
\[ D_1 \ge D_2 \ge \cdots \ge D_N \]
Simply checking whether \(L_i \le U_i\) for each \(i\) is insufficient.
For example, in the case:
\[ D_1 \in [0, 0], \quad D_2 \in [1, 1] \]
each can be chosen individually, but it’s impossible to satisfy \(D_1 \ge D_2\).
This check can be done greedily from left to right.
Let prev be the current maximum selectable value.
At position \(i\), \(D_i\) must satisfy:
- At most the previous value, i.e., \(D_i \le prev\)
- Within the interval, i.e., \(D_i \le U_i\)
Therefore, the maximum selectable value is:
\[ \min(prev, U_i) \]
If this is less than \(L_i\), no value can satisfy the conditions, so it fails.
Otherwise, we choose that maximum value as \(D_i\).
Choosing the maximum value is optimal because subsequent values must be “at most the current value,” so making the current value as large as possible maximizes the freedom for later positions.
Additionally, \(X_L\) and \(X_R\) for each split position \(k\) can be computed efficiently using prefix XOR.
Let total be the XOR of the entire string and px[k] be the XOR of the first \(k\) characters. Then:
\[ X_L = px[k] \]
\[ X_R = total \oplus X_L \]
This is because:
\[ total = X_L \oplus X_R \]
and XOR has the property:
\[ x \oplus x = 0 \]
Algorithm
- Convert string \(S\) to an array of ASCII codes
vals. - Build the prefix XOR array
px.px[i]is the XOR of the first \(i\) characters.
- For each value \(a = 0, 1, \ldots, 127\), precompute:
low[a] = max(0, 97 - a)high[a] = 122 - a
- Try all split positions \(k = 1, 2, \ldots, N-1\).
- For each \(k\):
- Compute \(X_L = px[k]\)
- Compute \(X_R = px[N] \oplus X_L\)
- Compute the transformed values \(A_i\) from left to right and greedily check using the range of correction values \(D_i\).
- Initialize
prevto a sufficiently large value, e.g.,123. - For each \(A_i\), the maximum selectable value is
min(prev, high[A_i]). - If it is less than
low[A_i], it fails. - Otherwise, update
prevto that value.
- Initialize
- If no failure occurs until the end, that \(k\) is a valid split position, so increment the answer by \(1\).
Complexity
- Time complexity: \(O(N^2)\)
- Space complexity: \(O(N)\)
For each split position, we check up to \(N\) characters, so the total is \(O(N^2)\).
Since the constraint is \(N \le 5000\), this is well within the time limit.
Implementation Notes
In Python, reading the string as
bytesallows you to treat each character directly as an ASCII code integer.vals = list(data[1])Since ASCII codes are between \(0\) and \(127\),
lowandhighcan be precomputed as arrays of length \(128\).We set
prev = 123because the maximum possible correction value is at most \(122\).
Therefore,123serves as a sufficiently large value representing “no restriction initially.”Source Code
import sys
def main():
data = sys.stdin.buffer.read().split()
N = int(data[0])
vals = list(data[1])
px = [0] * (N + 1)
x = 0
for i in range(N):
x ^= vals[i]
px[i + 1] = x
total = x
low = [0] * 128
high = [0] * 128
for a in range(128):
high[a] = 122 - a
if a < 97:
low[a] = 97 - a
ans = 0
v = vals
lo = low
hi = high
p = px
n = N
tot = total
for k in range(1, n):
xl = p[k]
xr = tot ^ xl
prev = 123
ok = True
for i in range(k):
a = v[i] ^ xr
u = hi[a]
if prev > u:
prev = u
if prev < lo[a]:
ok = False
break
if ok:
for i in range(k, n):
a = v[i] ^ xl
u = hi[a]
if prev > u:
prev = u
if prev < lo[a]:
ok = False
break
if ok:
ans += 1
print(ans)
if __name__ == "__main__":
main()
This editorial was generated by gpt-5.5-high.
posted:
last update: