Submission #928986

#TimeUsernameProblemLanguageResultExecution timeMemory
928986minhnhatnoeAlice, Bob, and Circuit (APIO23_abc)C++17
0 / 100
2 ms856 KiB
#include "abc.h"
#include <bits/stdc++.h>
using namespace std;

namespace string_encode
{
    const int length_offset[5] = {0, 0, 26,
                                  26 + 26 * 26,
                                  26 + 26 * 26 + 26 * 26 * 26};
    int ctoi(const char *a)
    {
        int ptr = 0, result = 0;
        for (; a[ptr]; ptr++)
            result = result * 26 + a[ptr] - 'a';
        return result + length_offset[ptr];
    }
}

// Alice
int // returns la
alice(
    /*  in */ const int n,
    /*  in */ const char names[][5],
    /*  in */ const unsigned short numbers[],
    /* out */ bool outputs_alice[])
{
    vector<int> name(n);
    for (int i = 0; i < n; i++)
        name[i] = string_encode::ctoi(names[i]);

    vector<unsigned short> nums(n);
    copy(numbers, numbers + n, nums.begin());
}

// Bob
int // returns lb
bob(
    /*  in */ const int m,
    /*  in */ const char senders[][5],
    /*  in */ const char recipients[][5],
    /* out */ bool outputs_bob[])
{
    vector<pair<int, int>> msg(m);
    for (int i = 0; i < m; i++)
        msg[i] = {string_encode::ctoi(senders[i]),
                  string_encode::ctoi(recipients[i])};
}

namespace bit_store
{
    struct bit
    {
        int v = -1;
        bool is_stpd() const
        {
            return v == -1;
        }
    };
    bit zero, one;

    enum OP
    {
        OP_ZERO,        // f(OP_ZERO,    x0, x1) = 0
        OP_NOR,         // f(OP_NOR,     x0, x1) = !(x0 || x1)
        OP_GREATER,     // f(OP_GREATER, x0, x1) = (x0 > x1)
        OP_NOT_X1,      // f(OP_NOT_X1,  x0, x1) = !x1
        OP_LESS,        // f(OP_LESS,    x0, x1) = (x0 < x1)
        OP_NOT_X0,      // f(OP_NOT_X0,  x0, x1) = !x0
        OP_XOR,         // f(OP_XOR,     x0, x1) = (x0 ^ x1)
        OP_NAND,        // f(OP_NAND,    x0, x1) = !(x0 && x1)
        OP_AND,         // f(OP_AND,     x0, x1) = (x0 && x1)
        OP_EQUAL,       // f(OP_EQUAL,   x0, x1) = (x0 == x1)
        OP_X0,          // f(OP_X0,      x0, x1) = x0
        OP_GEQ,         // f(OP_GEQ,     x0, x1) = (x0 >= x1)
        OP_X1,          // f(OP_X1,      x0, x1) = x1
        OP_LEQ,         // f(OP_LEQ,     x0, x1) = (x0 <= x1)
        OP_OR,          // f(OP_OR,      x0, x1) = (x0 || x1)
        OP_ONE,         // f(OP_ONE,     x0, x1) = 1
        NOT_CONSTRUCTED // Input bits
    };

    // Construction of bit
    struct bcstr
    {
        OP op;
        bit x, y;
    };
}
namespace num_store
{
    struct num
    {
        static const int MAXSIZE = 19;
        bit_store::bit bits[MAXSIZE];
        num() {}

        void init_input(const int SIZE);
        void init_value(int v);
    };
}
namespace bit_mani
{
    using namespace bit_store;
    struct io_bits
    {
        bit zero, one;
        int input_size = 0, input_ptr = 0;
        vector<bcstr> cstr;
        bit make_bit(OP op, bit x, bit y)
        {
            assert(x.v != -1 && y.v != -1 && op != NOT_CONSTRUCTED);
            cstr.push_back({op, x, y});
            return bit{int(cstr.size() - 1)};
        };

        io_bits() {}
        io_bits(int input_size) : input_size(input_size), cstr(input_size, {NOT_CONSTRUCTED})
        {
            zero = make_bit(OP_ZERO, bit{0}, bit{0});
            one = make_bit(OP_ONE, bit{0}, bit{0});
        }
        void erase_deps(vector<num_store::num> &results)
        {
            vector<int> act(cstr.size());
            for (int i = 0; i < input_size; i++)
                act[i] = 1;

            for (num_store::num &v : results)
            {
                for (bit &x : v.bits)
                {
                    x = x.is_stpd() ? zero : x;
                    act[x.v] = 1;
                }
            }

            for (int i = act.size() - 1; i >= input_size; i--)
            {
                if (act[i] == 0)
                    continue;
                assert(cstr[i].x.v < i && cstr[i].y.v < i);
                act[cstr[i].x.v] = act[cstr[i].y.v] = 1;
            }

            int cnt = 0;
            vector<bcstr> s;
            for (int i = 0; i < cstr.size(); i++)
            {
                if (act[i] == 0)
                    continue;
                act[i] = cnt++;
                s.push_back({cstr[i].op, bit{act[cstr[i].x.v]}, bit{act[cstr[i].y.v]}});
            }
            cstr = move(s);

            for (num_store::num &v : results)
            {
                for (bit &x : v.bits)
                    x.v = act[x.v];
            }
        }
        int write(int ops[], int opers[][2], int outputs[][16], vector<num_store::num> &results){
            erase_deps(results);
            for (int i = input_size; i < cstr.size(); i++)
            {
                ops[i] = cstr[i].op;
                opers[i][0] = cstr[i].x.v;
                opers[i][1] = cstr[i].y.v;
            }
            for (int i = 0; i < results.size(); i++)
                for (int j = 0; j < 16; j++)
                    outputs[i][j] = results[i].bits[j].v;
            return cstr.size();
        }
    } strm;

#define DEF_OP(op, name) \
    bit operator op(const bit &a, const bit &b) { return strm.make_bit(name, a, b); }
    DEF_OP(^, OP_XOR)
    DEF_OP(&, OP_AND)
    DEF_OP(|, OP_OR)
    DEF_OP(==, OP_EQUAL)
#undef DEF_OP
}
namespace num_store{
    using bit_mani::strm;
    void num_store::num::init_input(const int SIZE)
    {
        for (int i = 0; i < SIZE; i++)
            bits[i].v = strm.input_ptr++;
        for (int i = SIZE; i < MAXSIZE; i++)
            bits[i] = strm.zero;
    }
    void num_store::num::init_value(int v)
    {
        for (int i = 0; i < MAXSIZE; i++)
            bits[i] = (v & (1 << i)) ? strm.one : strm.zero;
    }
}
namespace num_mani
{
    using num_store::num;
    using namespace bit_mani;
    using bit_mani::operator&, bit_mani::operator^, bit_mani::operator|, bit_mani::operator==;
    num operator+(const num &l, const num &r)
    {
        num result;
        int ptr = 0;
        for (; ptr < 16 && (l.bits[ptr].is_stpd() && r.bits[ptr].is_stpd()); ptr++)
            result.bits[ptr].v = -1;

        for (; ptr < 16 && (l.bits[ptr].is_stpd() || r.bits[ptr].is_stpd()); ptr++)
            result.bits[ptr] = (l.bits[ptr].v != -1 ? l.bits[ptr] : r.bits[ptr]);

        for (bit three{-1}; ptr < 16; ptr++)
        {
            bit one = l.bits[ptr], two = r.bits[ptr];
            assert(one.v != -1 && two.v != -1);

            if (three.is_stpd())
            {
                result.bits[ptr] = one ^ two;
                three = one & two;
            }
            else
            {
                bit four = one ^ two;
                bit five = result.bits[ptr] = four ^ three;
                bit six = one & two;
                bit seven = four & three;
                three = six | seven;
            }
        }

        return result;
    }
    num operator<<(const num &a, int b)
    {
        num result;
        copy(a.bits, a.bits + 16 - b, result.bits + b);
        return result;
    }
    num operator&(const num &a, const bit &g)
    {
        num result;
        for (int i = 0; i < 16; i++)
        {
            if (a.bits[i].is_stpd())
                continue;
            result.bits[i] = a.bits[i] & g;
        }
        return result;
    }
    num operator*(const num &lhs, const num &rhs)
    {
        int sizeab = strm.cstr.size();
        num ab;
        {
            num nb = rhs;
            for (int i = 0; i < 16; i++)
            {
                if (lhs.bits[i].is_stpd())
                    continue;
                num anb = nb & lhs.bits[i];
                ab = ab + anb;
                nb = nb << 1;
            }
            sizeab = strm.cstr.size() - sizeab;
        }

        int sizeba = strm.cstr.size();
        num ba;
        {
            num na = lhs;
            for (int i = 0; i < 16; i++)
            {
                if (rhs.bits[i].is_stpd())
                    continue;
                num ana = na & rhs.bits[i];
                ba = ba + ana;
                na = na << 1;
            }
            sizeba = strm.cstr.size() - sizeab;
        }

        if (sizeab <= sizeba)
            return ab;
        else
            return ba;
    }
    num operator|(const num &lhs, const num &rhs)
    {
        num result;
        for (int i = 0; i < 16; i++)
        {
            if (lhs.bits[i].is_stpd())
                result.bits[i] = rhs.bits[i];
            else if (rhs.bits[i].is_stpd())
                result.bits[i] = lhs.bits[i];
            else
                result.bits[i] = lhs.bits[i] | rhs.bits[i];
        }
        return result;
    }
    bit operator==(num lhs, num rhs)
    {
        bit result{-1};
        for (int i = 0; i < 16; i++)
        {
            if (lhs.bits[i].is_stpd() && rhs.bits[i].is_stpd())
                continue;
            if (lhs.bits[i].is_stpd())
                lhs.bits[i] = zero;
            if (rhs.bits[i].is_stpd())
                rhs.bits[i] = zero;
            bit eq = (lhs.bits[i] == rhs.bits[i]);
            if (result.is_stpd())
                result = eq;
            else
                result = result & eq;
        }
        return result;
    }
}

namespace circuit_helpers
{
    using num_store::num;
    using bit_store::bit;
    using bit_mani::strm;
    using bit_mani::operator&, bit_mani::operator^, bit_mani::operator|, bit_mani::operator==;
    using num_mani::operator+, num_mani::operator&, num_mani::operator|, num_mani::operator==;

    int run(int la, int lb, int ops[], int opers[][2], int outputs[][16])
    {
        bit_mani::strm = bit_mani::io_bits(la + lb);

        int n = la / 32;

        vector<num> aweight(n);
        for (int i = 0; i < n; i++)
            aweight[i].init_input(16);

        vector<num> aposi(n);
        for (int i = 0; i < n; i++)
            aposi[i].init_input(16);

        vector<vector<bit>> g(n, vector<bit>(n));
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++)
                g[i][j].v = strm.input_ptr++;
        
        assert(strm.input_ptr == strm.input_size);

        vector<num> tresult(n);
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++)
                tresult[j] = tresult[j] + (aweight[i] & g[i][j]);

        vector<num> result(n);
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < n; j++)
            {
                num jn;
                jn.init_value(j);
                result[i] = result[i] + (tresult[j] & (aposi[i] == jn));
            }
        }

        return strm.write(ops, opers, outputs, result);
    }
}

// Circuit
int // returns l
circuit(
    /*  in */ const int la,
    /*  in */ const int lb,
    /* out */ int operations[],
    /* out */ int operands[][2],
    /* out */ int outputs_circuit[][16])
{
    return circuit_helpers::run(la, lb, operations, operands, outputs_circuit);
}

Compilation message (stderr)

abc.cpp: In function 'int alice(int, const char (*)[5], const short unsigned int*, bool*)':
abc.cpp:33:1: warning: no return statement in function returning non-void [-Wreturn-type]
   33 | }
      | ^
abc.cpp: In function 'int bob(int, const char (*)[5], const char (*)[5], bool*)':
abc.cpp:47:1: warning: no return statement in function returning non-void [-Wreturn-type]
   47 | }
      | ^
abc.cpp: In member function 'void bit_mani::io_bits::erase_deps(std::vector<num_store::num>&)':
abc.cpp:147:31: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<bit_store::bcstr>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  147 |             for (int i = 0; i < cstr.size(); i++)
      |                             ~~^~~~~~~~~~~~~
abc.cpp: In member function 'int bit_mani::io_bits::write(int*, int (*)[2], int (*)[16], std::vector<num_store::num>&)':
abc.cpp:164:40: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<bit_store::bcstr>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  164 |             for (int i = input_size; i < cstr.size(); i++)
      |                                      ~~^~~~~~~~~~~~~
abc.cpp:170:31: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<num_store::num>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  170 |             for (int i = 0; i < results.size(); i++)
      |                             ~~^~~~~~~~~~~~~~~~
abc.cpp: In function 'num_store::num num_mani::operator+(const num_store::num&, const num_store::num&)':
abc.cpp:228:21: warning: variable 'five' set but not used [-Wunused-but-set-variable]
  228 |                 bit five = result.bits[ptr] = four ^ three;
      |                     ^~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...