#include <bits/stdc++.h>
using namespace std;

struct Edge {
    int a, b;
    int r, c;
    char move_ab;
};

static const string ALPH = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static const int CHUNK_BITS = 1400;

static vector<Edge> build_edges(int n) {
    int m = (n + 1) / 2;
    vector<Edge> edges;
    edges.reserve(2 * m * max(0, m - 1));
    auto id = [m](int i, int j) { return i * m + j; };
    for (int i = 0; i < m; ++i) {
        for (int j = 0; j < m; ++j) {
            int u = id(i, j);
            if (j + 1 < m) {
                edges.push_back({u, id(i, j + 1), 2 * i + 1, 2 * j + 2, 'R'});
            }
            if (i + 1 < m) {
                edges.push_back({u, id(i + 1, j), 2 * i + 2, 2 * j + 1, 'D'});
            }
        }
    }
    return edges;
}

static string encode_bits(const vector<int>& bits) {
    string out;
    for (int i = 0; i < (int)bits.size(); i += 6) {
        int v = 0;
        for (int k = 0; k < 6; ++k) {
            if (i + k < (int)bits.size() && bits[i + k]) v |= (1 << k);
        }
        out.push_back(ALPH[v]);
    }
    return out;
}

static void decode_bits(const string& encoded, int count, vector<int>& out) {
    static array<int, 256> rev;
    static bool ready = false;
    if (!ready) {
        rev.fill(-1);
        for (int i = 0; i < (int)ALPH.size(); ++i) {
            rev[(unsigned char)ALPH[i]] = i;
        }
        ready = true;
    }
    out.clear();
    out.reserve(count);
    for (char ch : encoded) {
        int v = rev[(unsigned char)ch];
        if (v < 0) continue;
        for (int k = 0; k < 6 && (int)out.size() < count; ++k) {
            out.push_back((v >> k) & 1);
        }
    }
}

static string ask_cell(int r, int c) {
    cout << "? " << r << ' ' << c << '\n' << flush;
    string reply;
    if (!(cin >> reply)) exit(0);
    return reply;
}

static void send_message(int target, const string& body) {
    cout << "> " << target << ' ' << body << '\n' << flush;
    string ok;
    if (!(cin >> ok)) exit(0);
}

static void receive_any(int& sender, string& body) {
    cout << "< ?" << '\n' << flush;
    string line;
    getline(cin, line);
    if (line.empty()) getline(cin, line);
    if (line == "- -") {
        sender = -1;
        body.clear();
        return;
    }
    size_t sp = line.find(' ');
    if (sp == string::npos) {
        sender = -1;
        body.clear();
        return;
    }
    sender = stoi(line.substr(0, sp));
    body = line.substr(sp + 1);
}

static void query_partition(
    int agent_id,
    int num_agents,
    const vector<Edge>& edges,
    vector<signed char>* master_open
) {
    vector<int> chunk;
    chunk.reserve(CHUNK_BITS);
    auto flush_chunk = [&]() {
        if (chunk.empty()) return;
        string body = "B " + to_string((int)chunk.size()) + " " + encode_bits(chunk);
        send_message(0, body);
        chunk.clear();
    };

    for (int e = agent_id; e < (int)edges.size(); e += num_agents) {
        if (master_open && (*master_open)[e] != -1) continue;
        int bit = ask_cell(edges[e].r, edges[e].c) == "1";
        if (master_open) {
            (*master_open)[e] = (signed char)bit;
        } else {
            chunk.push_back(bit);
            if ((int)chunk.size() >= CHUNK_BITS) flush_chunk();
        }
    }
    if (!master_open) {
        flush_chunk();
        send_message(0, "D");
        cout << "halt" << '\n' << flush;
        exit(0);
    }
}

static string build_path(int n, const vector<Edge>& edges, const vector<signed char>& open) {
    int m = (n + 1) / 2;
    int rooms = m * m;
    vector<vector<pair<int, char>>> g(rooms);
    for (int i = 0; i < (int)edges.size(); ++i) {
        if (open[i] != 1) continue;
        const Edge& e = edges[i];
        g[e.a].push_back({e.b, e.move_ab});
        char back = (e.move_ab == 'R') ? 'L' : 'U';
        g[e.b].push_back({e.a, back});
    }

    vector<int> parent(rooms, -1);
    vector<char> parent_move(rooms, 0);
    queue<int> q;
    parent[0] = 0;
    q.push(0);
    while (!q.empty()) {
        int u = q.front();
        q.pop();
        if (u == rooms - 1) break;
        for (auto [v, mv] : g[u]) {
            if (parent[v] != -1) continue;
            parent[v] = u;
            parent_move[v] = mv;
            q.push(v);
        }
    }

    if (parent[rooms - 1] == -1) {
        // Should never happen after all edge cells are known. Prefer a no-claim
        // timeout over an invalid claim if something goes badly wrong.
        while (true) {
            cout << "." << '\n' << flush;
            string ok;
            if (!(cin >> ok)) exit(0);
        }
    }

    vector<char> room_moves;
    for (int v = rooms - 1; v != 0; v = parent[v]) {
        room_moves.push_back(parent_move[v]);
    }
    reverse(room_moves.begin(), room_moves.end());

    string path;
    path.reserve(room_moves.size() * 2);
    for (char mv : room_moves) {
        path.push_back(mv);
        path.push_back(mv);
    }
    return path;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n, num_agents, agent_id, max_msg_len;
    if (!(cin >> n >> num_agents >> agent_id >> max_msg_len)) return 0;

    if (n == 1) {
        if (agent_id == 0) {
            cout << "!" << '\n' << flush;
        } else {
            cout << "halt" << '\n' << flush;
        }
        return 0;
    }

    vector<Edge> edges = build_edges(n);

    if (agent_id != 0) {
        query_partition(agent_id, num_agents, edges, nullptr);
        return 0;
    }

    vector<signed char> open(edges.size(), -1);

    query_partition(0, num_agents, edges, &open);

    vector<int> next_edge(num_agents);
    for (int id = 1; id < num_agents; ++id) next_edge[id] = id;

    int done = 0;
    vector<int> bits;
    while (done < num_agents - 1) {
        int sender;
        string body;
        receive_any(sender, body);
        if (sender <= 0 || sender >= num_agents) continue;
        if (body == "D") {
            ++done;
            continue;
        }
        if (body.rfind("B ", 0) == 0) {
            size_t p = body.find(' ', 2);
            if (p == string::npos) continue;
            int count = stoi(body.substr(2, p - 2));
            string encoded = body.substr(p + 1);
            decode_bits(encoded, count, bits);
            for (int bit : bits) {
                int e = next_edge[sender];
                while (e < (int)edges.size() && e % num_agents != sender) e++;
                if (e >= (int)edges.size()) break;
                open[e] = (signed char)bit;
                next_edge[sender] = e + num_agents;
            }
        }
    }

    string path = build_path(n, edges, open);
    cout << "! " << path << '\n' << flush;
    return 0;
}
