Submission #1195577

#TimeUsernameProblemLanguageResultExecution timeMemory
1195577tutisMessage (IOI24_message)C++20
0 / 100
3417 ms1348 KiB
#pragma GCC target("avx2")
#pragma GCC optimization("O3")
#pragma GCC optimization("unroll-loops")
#include "message.h"
#include <algorithm>
#include <chrono>
#include <iostream>
#include <random>
#include <bitset>
#include <vector>
#include <deque>
#include <assert.h>
#include <math.h>

using namespace std;

int counter = 0;

bitset<31> masks[200];
int choose[32][32];
const int64_t seed1 = 5;
int tests = 10000;

bitset<31> globC;

bool initialized = false;

mt19937_64 rngSending(0);
bitset<31> send(bitset<31> A, bitset<31> C)
{
    if (counter >= 199)
    {
        assert(false);
    }
    A = A ^ masks[counter];
    vector<bool> Avector(31);
    for (int i = 0; i < 31; i++)
    {
        Avector[i] = A[i];
        if (C[i])
        {
            Avector[i] = rngSending() % 2;
        }
    }
    vector<bool> recVector = send_packet(Avector);
    bitset<31> received;
    for (int j = 0; j < 31; j++)
    {
        received[j] = recVector[j];
    }
    received = received ^ masks[counter];
    counter++;
    return received;
}

const int Q = 66;

int pos(bitset<31> C, int n, int k)
{
    if (k == 0)
    {
        return 1;
    }
    if (C[n - 1])
    {
        return choose[n - 1][k] + pos(C, n - 1, k - 1);
    }
    else
    {
        return pos(C, n - 1, k);
    }
}

bitset<31> kth(int n, int k, int pos)
{
    if (pos > choose[n][k])
    {
        return 0;
    }
    if (n == k)
    {
        bitset<31> ret;
        for (int i = 0; i < n; i++)
        {
            ret[i] = true;
        }
        return ret;
    }
    if (k == 0)
    {
        return bitset<31>(0);
    }
    if (pos <= choose[n - 1][k])
    {
        return kth(n - 1, k, pos);
    }
    bitset<31> c = kth(n - 1, k - 1, pos - choose[n - 1][k]);
    c[n - 1] = true;
    return c;
}

deque<bool> prepareBits(vector<bool> M, bitset<31> C)
{
    deque<bool> X;
    mt19937_64 rng(C.to_ullong());
    int offset = 1024 - M.size();
    for (int i = 0; i < offset; i++)
    {
        X.push_back(1);
    }
    X.push_back(0);
    for (int v : M)
    {
        X.push_back(v);
    }
    for (int i = 0; i < Q * 16 - 1025 - 23; i++)
    {
        X.push_back(rng() % 2 == 1);
    }
    assert(X.size() == Q * 16 - 23);
    return X;
}

void init()
{
    counter = 0;
    if (!initialized)
    {
        for (int n = 0; n < 32; n++)
        {
            for (int k = 0; k <= n; k++)
            {
                if (k == 0 || n == 0)
                {
                    choose[n][k] = 1;
                }
                else
                {
                    choose[n][k] = choose[n - 1][k] + choose[n - 1][k - 1];
                }
            }
        }
        mt19937_64 rng(seed1);
        for (int i = 0; i < 200; i++)
        {
            for (int j = 0; j < 31; j++)
            {
                masks[i] = rng();
            }
        }
    }
    initialized = true;
}

void send_message(vector<bool> M, vector<bool> Cvect)
{
    init();
    bitset<31> C;
    for (int i = 0; i < 31; i++)
    {
        C[i] = Cvect[i];
    }
    globC = C;
    bitset<29> CC = pos(C, 31, 15);
    deque<bool> X = prepareBits(M, C);
    int pos = (CC.to_ullong() - 1) / 6678671; // 0...44
    assert(pos < 45);
    bitset<23> posBits = (CC.to_ullong() - 1) % 6678671;
    vector<bitset<31>> V(Q);
    int c = 0;
    for (int j = 0; j < 31; j++)
    {
        if (C[j])
        {
            continue;
        }
        for (int i = 0; i < Q; i++)
        {
            if (c / 23 == pos)
            {
                V[i][j] = posBits[c % 23];
            }
            else
            {
                V[i][j] = X.front();
                X.pop_front();
            }
            c++;
        }
    }
    for (bitset<31> v : V)
    {
        send(v, C);
    }
}

std::vector<bool> receive_message(vector<vector<bool>> Rvect)
{
    init();
    vector<bitset<31>> R(Rvect.size());
    for (int i = 0; i < int(Rvect.size()); i++)
    {
        bitset<31> b;
        for (int j = 0; j < 31; j++)
        {
            b[j] = Rvect[i][j];
        }
        R[i] = b;
    }
    for (int i = 0; i < int(R.size()); i++)
    {
        R[i] = R[i] ^ masks[i];
    }
    if (R.size() != Q)
    {
        assert(false);
    }
    for (int pos = 0; pos < 45; pos++)
    {
        vector<int> posCC;
        for (int c1 = 0; c1 <= 31; c1++)
        {
            for (int c2 = c1 + 1; c2 <= 32; c2++)
            {
                if (c2 != 32)
                {
                    bitset<132> x;
                    for (int i = 0; i < 66; i++)
                    {
                        x[i] = R[i][c1];
                    }
                    for (int i = 0; i < 66; i++)
                    {
                        x[i + 66] = R[i][c2];
                    }
                    for (int s = 0; s + 23 <= x.size(); s++)
                    {
                        bitset<132> shifted = x >> s;
                        for (int i = 23; i < shifted.size(); i++)
                        {
                            shifted[i] = 0;
                        }
                        bitset<23> casted = shifted.to_ullong() & ((1 << 23) - 1);
                        posCC.push_back(casted.to_ullong() + 6678671 * pos + 1);
                    }
                }
                else
                {
                    bitset<66> x;
                    for (int i = 0; i < 66; i++)
                    {
                        x[i] = R[i][c1];
                    }
                    for (int s = 0; s + 23 <= x.size(); s++)
                    {
                        bitset<66> shifted = x >> s;
                        for (int i = 23; i < shifted.size(); i++)
                        {
                            shifted[i] = 0;
                        }
                        bitset<23> casted = shifted.to_ullong() & ((1 << 23) - 1);
                        posCC.push_back(casted.to_ullong() + 6678671 * pos + 1);
                    }
                }
            }
        }
        sort(posCC.begin(), posCC.end());
        posCC.resize(unique(posCC.begin(), posCC.end()) - posCC.begin());
        for (bitset<29> cc : posCC)
        {
            bitset<31> C = kth(31, 15, cc.to_ullong());
            if (C.count() != 15)
            {
                continue;
            }
            bitset<23> posBits = (cc.to_ullong() - 1) % 6678671;

            deque<bool> X;
            int c = 0;
            bool ok = true;
            for (int j = 0; j < 31; j++)
            {
                if (C[j])
                {
                    continue;
                }
                for (int i = 0; i < Q; i++)
                {
                    if (c / 23 == pos)
                    {
                        ok &= R[i][j] == posBits[c % 23];
                    }
                    else
                    {
                        X.push_back(R[i][j]);
                    }
                    c++;
                }
            }
            if (!ok)
            {
                continue;
            }
            mt19937_64 rng(C.to_ullong());
            for (int i = 1025; i < int(X.size()); i++)
            {
                bool v = rng() % 2 == 1;
                bool w = X[i];
                if (v != w)
                {
                    ok = false;
                    break;
                }
            }
            if (!ok)
            {
                continue;
            }
            while (X.size() > 1025)
            {
                X.pop_back();
            }
            int offset = 0;
            while (offset < int(X.size()) && X[offset])
            {
                offset++;
            }
            vector<bool> answer;
            for (int i = offset + 1; i < int(X.size()); i++)
            {
                answer.push_back(X[i]);
            }
            while (answer.size() < 1025)
            {
                answer.push_back(0);
            }
            while ((1024 - int(answer.size())) != offset && answer.size() > 0)
            {
                answer.pop_back();
            }
            return answer;
        }
    }
    assert(false);
    return {};
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...