D - ビーズ列 / Bead Sequence 解説 by admin
gpt-5.5-xhighOverview
This problem asks you to find the shortest distance from \(S\) to \(T\) on a graph where states are A/B strings of length \(N\), and transitions are defined by 3 types of operations.
Since all operations have a cost of \(1\), we find the minimum number of operations using breadth-first search (BFS).
Analysis
Since operations can be performed any number of times, if we simply try to “enumerate all possibilities up to a certain number of steps,” we may revisit the same state multiple times, potentially causing the search to continue indefinitely.
However, since bead sequences are A/B strings of length \(N\), the number of possible states is at most
\(2^N\)
Given the constraint \(N \leq 25\), we can treat all states as vertices in a graph.
The operations available from each state are as follows:
- Rotate left
- Rotate right
- For each positive divisor \(d\) of \(N\) (\(d < N\)), repeat the first \(d\) characters
Since all operations have cost \(1\), using BFS guarantees that the distance when we first reach \(T\) is the minimum number of operations.
Additionally, handling strings directly would cost \(O(N)\) for rotations and comparisons.
Instead, we encode A as 0 and B as 1, representing strings as integer bit sequences.
For example, the string ABBA can be represented as follows:
A\(\rightarrow 0\)B\(\rightarrow 1\)
By storing each character as a bit, we can efficiently perform rotations and extraction of the first \(d\) characters using bitwise operations.
Algorithm
First, convert strings \(S, T\) to integers.
If the \(i\)-th character of the string is B, set the \(i\)-th bit of the integer to \(1\).
if (s[i] == 'B') v |= (1 << i);
This allows a string of length \(N\) to be represented as an integer between \(0\) and \(2^N - 1\).
Next, perform BFS.
For state \(x\), create the following transitions:
Left Rotation
Move the first character, i.e., bit \(0\), to the end, i.e., bit \(N-1\).
int leftRot = (x >> 1) | ((x & 1) << (N - 1));
Right Rotation
Move the last character, i.e., bit \(N-1\), to the front, i.e., bit \(0\).
int rightRot = ((x << 1) & fullMask) | (x >> (N - 1));
Here, fullMask = (1 << N) - 1 is used to clear unnecessary upper bits.
Pattern Duplication
Let \(d\) be a positive divisor of \(N\) with \(d < N\).
The first \(d\) characters of the current state \(x\) are the lower \(d\) bits.
int pattern = x & ((1 << d) - 1);
We create a string by repeating this pattern \(N/d\) times.
For example, if \(N = 6, d = 2\) and the leading pattern is AB, the result is:
ABABAB
In the code, computing this transformation every time would be slow, so we precompute it in a repeatTable.
table[p] = the state obtained by repeating p to length N
In BFS, when we reach an unvisited state, we record its distance.
dist[y] = dist[x] + 1;
If that state is the target target, we output the distance and terminate.
If BFS completes without reaching target, we output -1.
Complexity
Let \(D\) be the number of positive divisors \(d < N\) of \(N\).
The number of transitions examined from each state is \(O(D + 2)\) (left rotation, right rotation, and pattern duplication for each \(d\)).
- Time complexity: \(O(2^N \cdot D)\)
- Space complexity: \(O(2^N)\)
Implementation Notes
Representing strings as integer bit sequences allows fast state comparison and rotation.
In BFS,
dist[state] == -1is used to indicate an unvisited state.Precomputing pattern duplication for each divisor \(d\) means that during BFS, we only need to look up a table.
If \(S = T\), output
0immediately and terminate.Source Code
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int N;
string S, T;
cin >> N >> S >> T;
auto encode = [&](const string& s) {
int v = 0;
for (int i = 0; i < N; i++) {
if (s[i] == 'B') v |= (1 << i);
}
return v;
};
int start = encode(S);
int target = encode(T);
if (start == target) {
cout << 0 << '\n';
return 0;
}
int total = 1 << N;
int fullMask = total - 1;
vector<int> prefixMasks;
vector<vector<int>> repeatTable;
for (int d = 1; d < N; d++) {
if (N % d != 0) continue;
int sz = 1 << d;
vector<int> table(sz, 0);
for (int p = 0; p < sz; p++) {
int v = 0;
for (int pos = 0; pos < N; pos += d) {
v |= (p << pos);
}
table[p] = v;
}
prefixMasks.push_back(sz - 1);
repeatTable.push_back(move(table));
}
vector<int> dist(total, -1);
vector<int> q;
q.reserve(total);
dist[start] = 0;
q.push_back(start);
auto push_state = [&](int y, int nd) -> bool {
if (dist[y] != -1) return false;
dist[y] = nd;
if (y == target) {
cout << nd << '\n';
return true;
}
q.push_back(y);
return false;
};
for (size_t head = 0; head < q.size(); head++) {
int x = q[head];
int nd = dist[x] + 1;
int leftRot = (x >> 1) | ((x & 1) << (N - 1));
if (push_state(leftRot, nd)) return 0;
int rightRot = ((x << 1) & fullMask) | (x >> (N - 1));
if (push_state(rightRot, nd)) return 0;
for (size_t i = 0; i < repeatTable.size(); i++) {
int y = repeatTable[i][x & prefixMasks[i]];
if (push_state(y, nd)) return 0;
}
}
cout << -1 << '\n';
return 0;
}
This editorial was generated by gpt-5.5-xhigh.
投稿日時:
最終更新: