Submission #1354292

#TimeUsernameProblemLanguageResultExecution timeMemory
1354292tickcrossyMessage (IOI24_message)C++20
0 / 100
248 ms748 KiB
#include <vector>

using namespace std;

// 选手不需要实现该函数,仅作声明
vector<bool> send_packet(vector<bool> A);

// 生成一个伪随机的映射,避免被自适应评测机抓到固定规律
void get_mapping(int map_k[31], int map_r[31]) {
    int counts[16] = {0};
    for (int i = 0; i < 31; i++) {
        // 使用简单的哈希步长打乱 C 的 31 个比特放在哪个安全列
        map_k[i] = (i * 13) % 16;
        while (counts[map_k[i]] == 2) {
            map_k[i] = (map_k[i] + 1) % 16;
        }
        // map_r 代表放在第 65 还是 66 个数据包 (索引为 65 和 66)
        map_r[i] = 65 + counts[map_k[i]];
        counts[map_k[i]]++;
    }
}

// Aisha 的发送策略
void send_message(vector<bool> M, vector<bool> C) {
    int S = M.size();
    vector<bool> P;
    
    // 1. 将长度 S 编码进前 11 个比特
    for (int i = 0; i < 11; i++) {
        P.push_back((S >> i) & 1);
    }
    // 2. 压入实际的消息 M
    for (int i = 0; i < S; i++) {
        P.push_back(M[i]);
    }
    // 3. 补齐到 1040 个比特 (16 列 * 每列前 65 个比特用于存数据 = 1040)
    while (P.size() < 1040) {
        P.push_back(0);
    }

    // 找出 16 个安全列
    vector<int> S_col;
    for (int i = 0; i < 31; i++) {
        if (!C[i]) S_col.push_back(i);
    }

    // 准备发送矩阵 data[col][packet_index]
    // 总共发送 67 个包,索引 0~66
    vector<vector<bool>> data(31, vector<bool>(67, 0));
    
    // 将 1040 个有效数据分配到 16 个安全列的前 65 个包中
    for (int k = 0; k < 16; k++) {
        int col = S_col[k];
        for (int i = 0; i < 65; i++) {
            data[col][i] = P[k * 65 + i];
        }
    }

    // 将 31 个比特的 C 分布式储存在 16 个安全列的最后 2 个包中
    int map_k[31], map_r[31];
    get_mapping(map_k, map_r);
    for (int i = 0; i < 31; i++) {
        int target_col = S_col[map_k[i]];
        data[target_col][map_r[i]] = C[i];
    }

    // 发送这 67 个数据包
    for (int p = 0; p < 67; p++) {
        vector<bool> A(31);
        for (int i = 0; i < 31; i++) {
            A[i] = data[i][p]; // Cleopatra 会改写其中 15 个,不用理会
        }
        send_packet(A);
    }
}

// Basma 的接收策略
vector<bool> receive_message(vector<vector<bool>> R) {
    int map_k[31], map_r[31];
    get_mapping(map_k, map_r);
    
    vector<bool> best_C;
    
    // 利用 DFS 剪枝爆破出那唯一的 16 个安全列组合
    auto dfs = [&](auto& self, int col, int k, vector<int>& current_C) -> bool {
        // 搜索到底部,且正好找齐了 16 个安全列
        if (col == 31) {
            if (k == 16) {
                best_C = vector<bool>(current_C.begin(), current_C.end());
                return true;
            }
            return false;
        }
        
        // 分支 1:假设当前列是【被篡改列】
        // 剩余的列必须足以凑齐 16 个安全列
        if (col - k < 15) {
            if (current_C[col] == -1 || current_C[col] == 1) { // 没有矛盾
                int old = current_C[col];
                current_C[col] = 1;
                if (self(self, col + 1, k, current_C)) return true;
                current_C[col] = old; // 回溯
            }
        }
        
        // 分支 2:假设当前列是【安全列】
        if (k < 16) {
            if (current_C[col] == -1 || current_C[col] == 0) { // 必须等于 0 (安全)
                vector<int> rollback_indices;
                vector<int> rollback_values;
                bool ok = true;
                
                auto set_val = [&](int idx, int val) {
                    if (current_C[idx] != -1 && current_C[idx] != val) {
                        ok = false; // 出现自相矛盾!立刻剪枝
                    } else if (current_C[idx] == -1) {
                        rollback_indices.push_back(idx);
                        rollback_values.push_back(-1);
                        current_C[idx] = val;
                    }
                };
                
                // 本列必定是 0
                set_val(col, 0);
                // 当前列作为第 k 个安全列,它最后两个包必须和 C 的相关位一致
                for (int i = 0; i < 31; i++) {
                    if (map_k[i] == k) {
                        set_val(i, R[map_r[i]][col]);
                    }
                }
                
                // 如果毫无矛盾,继续深搜
                if (ok) {
                    if (self(self, col + 1, k + 1, current_C)) return true;
                }
                
                // 还原现场 (回溯)
                for (size_t i = 0; i < rollback_indices.size(); i++) {
                    current_C[rollback_indices[i]] = rollback_values[i];
                }
            }
        }
        return false;
    };
    
    // 初始化时所有位置未知 (-1)
    vector<int> current_C(31, -1);
    dfs(dfs, 0, 0, current_C);
    
    // 根据最佳推导结果提取 S_col
    vector<int> S_col;
    for (int i = 0; i < 31; i++) {
        if (!best_C[i]) S_col.push_back(i);
    }
    
    // 提取所有数据
    vector<bool> P(1040);
    for (int k = 0; k < 16; k++) {
        int col = S_col[k];
        for (int i = 0; i < 65; i++) {
            P[k * 65 + i] = R[i][col];
        }
    }
    
    // 前 11 个比特解码出消息的原始长度 S
    int S = 0;
    for (int i = 0; i < 11; i++) {
        if (P[i]) S |= (1 << i);
    }
    
    // 截取 S 长度的原始消息
    vector<bool> M(S);
    for (int i = 0; i < S; i++) {
        M[i] = P[11 + i];
    }
    
    return M;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...