제출 #1354277

#제출 시각아이디문제언어결과실행 시간메모리
1354277tickcrossy메시지 (IOI24_message)C++20
0 / 100
3128 ms1216 KiB
#include <vector>
#include <cstdint>
#include <algorithm>

using namespace std;

vector<bool> send_packet(vector<bool> A);

// 强位混合哈希函数,避免任何冲突
uint64_t mix_hash(uint64_t x) {
    x ^= x >> 30;
    x *= 0xbf58476d1ce4e5b9ULL;
    x ^= x >> 27;
    x *= 0x94d049bb133111ebULL;
    x ^= x >> 31;
    return x;
}

// 提取指定列的哈希值,动态包含反馈历史
uint16_t get_h(int c, int round, int S, const vector<vector<bool>>& R) {
    uint64_t state = S ^ (round * 0x123456789ABCDEFULL) ^ c;
    for (size_t i = 0; i < R.size(); ++i) {
        state = mix_hash(state ^ (R[i][c] ? 0x9e3779b97f4a7c15ULL : 0));
    }
    return (state >> 16) & 0xFFFF;
}

void send_message(vector<bool> M, vector<bool> C) {
    int S = M.size();
    int D = (S + 15) / 16; // 需要的数据包数量
    
    vector<int> safe_cols;
    for (int i = 0; i < 31; ++i) {
        if (!C[i]) safe_cols.push_back(i);
    }
    
    vector<vector<bool>> R;
    int idx = 0;
    
    // 阶段1:发送原始数据包
    for (int p = 0; p < D; ++p) {
        vector<bool> A(31, false);
        for (int i = 0; i < 16; ++i) {
            if (idx < S) A[safe_cols[i]] = M[idx++];
        }
        R.push_back(send_packet(A));
    }
    
    // 阶段2:发送 4 轮基于反馈的验证包
    for (int round = 0; round < 4; ++round) {
        uint16_t h[31];
        for (int c = 0; c < 31; ++c) {
            h[c] = get_h(c, round, S, R);
        }
        
        uint16_t target = 0;
        for (int i = 0; i < 16; ++i) target ^= h[safe_cols[i]];
        
        vector<bool> A(31, false);
        for (int i = 0; i < 16; ++i) A[safe_cols[i]] = (target >> i) & 1;
        R.push_back(send_packet(A));
    }
}

// 中途相遇子集枚举生成器
void get_subsets(const vector<int>& cols, int k, vector<pair<uint64_t, int>>& res, 
                 const uint64_t* H, const uint64_t* V, int rank_offset) {
    int n = cols.size();
    int mask = (1 << k) - 1;
    while (mask < (1 << n)) {
        uint64_t val = 0;
        int rank = rank_offset;
        for (int i = 0; i < n; ++i) {
            if ((mask >> i) & 1) {
                int c = cols[i];
                val ^= H[c] ^ (V[c] << rank);
                rank++;
            }
        }
        res.push_back({val, mask});
        if (k == 0) break;
        uint32_t c_mask = mask & -mask;
        uint32_t r = mask + c_mask;
        mask = (((r ^ mask) >> 2) / c_mask) | r;
    }
}

vector<bool> receive_message(vector<vector<bool>> R) {
    int Q = R.size();
    int D = Q - 4; // 推算得知真实的数据包总数
    int min_S = max(1, (D - 1) * 16 + 1);
    int max_S = D * 16;

    // 猜测可能的原始数据量 S
    for (int S_guess = min_S; S_guess <= max_S; ++S_guess) {
        uint16_t h0[31], h1[31], h2[31], h3[31];
        
        vector<vector<bool>> R0(R.begin(), R.begin() + D);
        for (int c = 0; c < 31; ++c) h0[c] = get_h(c, 0, S_guess, R0);
        
        vector<vector<bool>> R1 = R0; R1.push_back(R[D]);
        for (int c = 0; c < 31; ++c) h1[c] = get_h(c, 1, S_guess, R1);
        
        vector<vector<bool>> R2 = R1; R2.push_back(R[D+1]);
        for (int c = 0; c < 31; ++c) h2[c] = get_h(c, 2, S_guess, R2);
        
        vector<vector<bool>> R3 = R2; R3.push_back(R[D+2]);
        for (int c = 0; c < 31; ++c) h3[c] = get_h(c, 3, S_guess, R3);
        
        uint64_t H[31];
        for (int c = 0; c < 31; ++c) {
            H[c] = ((uint64_t)h3[c] << 48) | ((uint64_t)h2[c] << 32) | ((uint64_t)h1[c] << 16) | h0[c];
        }
        
        uint64_t V[31];
        for (int c = 0; c < 31; ++c) {
            uint64_t v0 = R[D][c] ? 1 : 0;
            uint64_t v1 = R[D+1][c] ? 1 : 0;
            uint64_t v2 = R[D+2][c] ? 1 : 0;
            uint64_t v3 = R[D+3][c] ? 1 : 0;
            V[c] = (v3 << 48) | (v2 << 32) | (v1 << 16) | v0;
        }
        
        vector<int> left_cols, right_cols;
        for (int i = 0; i < 16; ++i) left_cols.push_back(i);
        for (int i = 16; i < 31; ++i) right_cols.push_back(i);
        
        // 极速匹配
        for (int k = 0; k <= 16; ++k) {
            if (k > 16 || (16 - k) > 15) continue;
            vector<pair<uint64_t, int>> left_res, right_res;
            get_subsets(left_cols, k, left_res, H, V, 0);
            get_subsets(right_cols, 16 - k, right_res, H, V, k);
            
            sort(left_res.begin(), left_res.end());
            sort(right_res.begin(), right_res.end());
            
            int i = 0, j = 0;
            while (i < left_res.size() && j < right_res.size()) {
                if (left_res[i].first == right_res[j].first) {
                    int maskL = left_res[i].second;
                    int maskR = right_res[j].second;
                    vector<int> S_cols;
                    for (int m = 0; m < 16; ++m) if ((maskL >> m) & 1) S_cols.push_back(left_cols[m]);
                    for (int m = 0; m < 15; ++m) if ((maskR >> m) & 1) S_cols.push_back(right_cols[m]);
                    
                    vector<bool> M_ret;
                    int msg_idx = 0;
                    for (int p = 0; p < D; ++p) {
                        for (int c = 0; c < 16; ++c) {
                            if (msg_idx < S_guess) {
                                M_ret.push_back(R[p][S_cols[c]]);
                                msg_idx++;
                            }
                        }
                    }
                    return M_ret; // 一旦符合反馈条件便立刻解构消息输出
                } else if (left_res[i].first < right_res[j].first) {
                    i++;
                } else {
                    j++;
                }
            }
        }
    }
    return {};
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...