제출 #1342785

#제출 시각아이디문제언어결과실행 시간메모리
1342785vjudge1메시지 (IOI24_message)C++17
100 / 100
401 ms824 KiB
#include "message.h"
#include <bits/stdc++.h>
using namespace std;

static const int N = 31;
static const int GOOD = 16;
static const int PACKETS = 66;
static const int PAYLOAD = 1025;

// ------------------------------------------------------------
// Helpers
// ------------------------------------------------------------

static vector<int> get_good_positions_from_C(const vector<bool>& C) {
    vector<int> a;
    for (int i = 0; i < N; ++i) {
        if (!C[i]) a.push_back(i);
    }
    return a; // size = 16, already sorted increasingly
}

static vector<int> get_diffs(const vector<int>& a) {
    vector<int> d(GOOD);
    for (int i = 0; i < GOOD; ++i) {
        d[i] = (a[(i + 1) % GOOD] - a[i] + N) % N;
        if (d[i] == 0) d[i] = N; // should never happen here
    }
    return d;
}

// T = 0...(1024-S times)...01M, total length = 1025
static vector<bool> build_payload(const vector<bool>& M) {
    vector<bool> T;
    T.reserve(PAYLOAD);

    int S = (int)M.size();
    int zeros = 1024 - S;
    for (int i = 0; i < zeros; ++i) T.push_back(false);
    T.push_back(true);
    for (bool b : M) T.push_back(b);

    return T;
}

// ------------------------------------------------------------
// Sender
// ------------------------------------------------------------

void send_message(std::vector<bool> M, std::vector<bool> C) {
    vector<int> a = get_good_positions_from_C(C);
    vector<int> d = get_diffs(a);
    vector<bool> T = build_payload(M);

    vector<vector<bool>> A(PACKETS, vector<bool>(N, false));

    int ptr = 0;

    // For each good column a[i]:
    // - first d[i] slots: one-hot encoding of d[i]  => 00...001
    // - remaining slots: payload bits
    for (int i = 0; i < GOOD; ++i) {
        int col = a[i];

        // one-hot code of value d[i]
        for (int r = 0; r < d[i] - 1; ++r) A[r][col] = false;
        A[d[i] - 1][col] = true;

        // remaining slots carry payload
        for (int r = d[i]; r < PACKETS; ++r) {
            A[r][col] = T[ptr++];
        }
    }

    // Exactly 31 overhead bits, so 66*16 - 31 = 1025 payload bits.
    // Hence ptr must be exactly PAYLOAD.
    for (int r = 0; r < PACKETS; ++r) {
        send_packet(A[r]);
    }
}

// ------------------------------------------------------------
// Receiver
// ------------------------------------------------------------

std::vector<bool> receive_message(std::vector<std::vector<bool>> R) {
    vector<int> nxt(N, 0);

    // For each position i, let first1(i) be the first packet (1..16)
    // where R[packet][i] == 1. For good positions this equals d_i.
    // Then define edge i -> (i + first1(i)) mod 31.
    // If there is no 1 in first 16 packets, the vertex cannot be good;
    // any arbitrary self-loop is fine.
    for (int i = 0; i < N; ++i) {
        int first = -1;
        for (int r = 0; r < GOOD; ++r) {
            if (R[r][i]) {
                first = r + 1; // 1-based
                break;
            }
        }
        if (first == -1) nxt[i] = i;               // arbitrary
        else nxt[i] = (i + first) % N;
    }

    // Find the unique directed cycle of length 16.
    vector<int> cycle;
    for (int start = 0; start < N; ++start) {
        vector<int> seen_order(N, -1);
        vector<int> path;
        int cur = start;
        bool ok = true;

        for (int step = 0; step < GOOD; ++step) {
            if (seen_order[cur] != -1) {
                ok = false;
                break;
            }
            seen_order[cur] = step;
            path.push_back(cur);
            cur = nxt[cur];
        }

        if (ok && cur == start) {
            cycle = path;
            break;
        }
    }

    sort(cycle.begin(), cycle.end()); // this is a1 < a2 < ... < a16

    vector<int> d = get_diffs(cycle);

    // Extract payload from the unused cells in the good columns.
    vector<bool> T;
    T.reserve(PAYLOAD);

    for (int i = 0; i < GOOD; ++i) {
        int col = cycle[i];
        for (int r = d[i]; r < PACKETS; ++r) {
            T.push_back(R[r][col]);
        }
    }

    // T has the form 0...01M. Return suffix after the first 1.
    int pos = 0;
    while (pos < (int)T.size() && !T[pos]) ++pos;

    vector<bool> M;
    for (int i = pos + 1; i < (int)T.size(); ++i) {
        M.push_back(T[i]);
    }
    return M;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...