답안 #927843

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
927843 2024-02-15T11:52:33 Z minhnhatnoe 앨리스, 밥, 서킷 (APIO23_abc) C++17
54 / 100
66 ms 15256 KB
#include "abc.h"
#include <bits/stdc++.h>
using namespace std;

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
};

namespace ab{
    int v[5];
    int ctoi(const char *a){
        int len = strlen(a);
        int x = 0;
        for (int i=0; i<len; i++){
            x = x * 26 + a[i] - 'a';
        }
        return x + v[len];
    }
    struct __init__{
        __init__(){
            v[1] = 0;
            v[2] = v[1] + 26;
            v[3] = v[2] + 26 * 26;
            v[4] = v[3] + 26 * 26 * 26;
        }
    } __init__;
}

// Alice
int // returns la
alice(
    /*  in */ const int n,
    /*  in */ const char names[][5],
    /*  in */ const unsigned short numbers[],
    /* out */ bool outputs_alice[])
{
    vector<pair<int, unsigned short>> a;
    for (int i=0; i<n; i++){
        a.emplace_back(ab::ctoi(names[i]), numbers[i]);
    }
    sort(a.begin(), a.end());

    int ptr = 0;
    for (int i=0; i<n; i++){
        for (int k=0; k<16; k++){
            outputs_alice[ptr++] = a[i].second & (1 << k);
        }
    }

    for (int i=0; i<n; i++){
        int v = ab::ctoi(names[i]);
        int pos = lower_bound(a.begin(), a.end(), pair<int, unsigned short>(v, 0)) - a.begin();
        assert(a[pos].first == v);
        for (int k=0; k<16; k++){
            outputs_alice[ptr++] = pos & (1 << k);
        }
    }
    return ptr;
}

// Bob
int // returns lb
bob(
    /*  in */ const int m,
    /*  in */ const char senders[][5],
    /*  in */ const char recipients[][5],
    /* out */ bool outputs_bob[])
{
    vector<int> pp;
    for (int i=0; i<m; i++){
        pp.emplace_back(ab::ctoi(senders[i]));
        pp.emplace_back(ab::ctoi(recipients[i]));
    }
    
    sort(pp.begin(), pp.end());
    pp.resize(unique(pp.begin(), pp.end()) - pp.begin());

    vector<vector<int>> g(pp.size(), vector<int> (pp.size()));
    for (int i=0; i<m; i++){
        int x = ab::ctoi(senders[i]); x = lower_bound(pp.begin(), pp.end(), x) - pp.begin();
        int y = ab::ctoi(recipients[i]); y = lower_bound(pp.begin(), pp.end(), y) - pp.begin();
        g[x][y]++;
    }

    int ptr = 0;
    for (int i=0; i<pp.size(); i++){
        for (int j=0; j<pp.size(); j++){
            outputs_bob[ptr++] = g[i][j];
        }
    }
    return ptr;
}

namespace circuit_ns{
    struct bit{
        int v = 0;
    };
    bit zero, one;
    struct bit_construct{
        OP p;
        bit x, y;
    };

    vector<bit_construct> a;
    bit create_gate(OP p, bit x, bit y){
        assert(x.v != -1 && y.v != -1);
        a.push_back({p, x, y});
        return bit{int(a.size()-1)};
    };

    #define DEF_OP(op, name) bit operator op (const bit &a, const bit &b){return create_gate(name, a, b);}

    DEF_OP(&, OP_AND)
    DEF_OP(|, OP_OR)
    DEF_OP(^, OP_XOR)
    DEF_OP(==, OP_EQUAL)

    #undef DEF_OP

    struct nbr{
        bit s[16];
        nbr(){
            memset(s, -1, sizeof s);
        }
        nbr(int spos){
            for (int i=0; i<16; i++) s[i].v = spos + i;
        }
        void init_value(int v){
            for (int i=0; i<16; i++){
                if (v & (1 << i)) s[i] = one;
                else s[i] = zero;
            }
        }
    };
    nbr operator+(const nbr &l, const nbr &r){
        nbr result;
        int ptr = 0;
        for (; ptr<16 && (l.s[ptr].v == -1 && r.s[ptr].v == -1); ptr++){
            result.s[ptr].v = -1;
        }
        for (; ptr<16 && (l.s[ptr].v == -1 || r.s[ptr].v == -1); ptr++){
            result.s[ptr] = (l.s[ptr].v != -1 ? l.s[ptr] : r.s[ptr]);
        }

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

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

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

        int sizeba = a.size();
        nbr ba;
        {
            nbr na = lhs;
            for (int i=0; i<16; i++){
                if (rhs.s[i].v == -1) continue;
                nbr ana = na & rhs.s[i];
                ba = ba + ana;
                na = na << 1;
            }
            sizeba = a.size() - sizeab;
        }

        if (sizeab <= sizeba) return ab;
        else return ba;
    }
    nbr operator|(const nbr &lhs, const nbr &rhs){
        nbr result;
        for (int i=0; i<16; i++){
            if (lhs.s[i].v == -1) result.s[i] = rhs.s[i];
            else if (rhs.s[i].v == -1) result.s[i] = lhs.s[i];
            else result.s[i] = lhs.s[i] | rhs.s[i];
        }
        return result;
    }
    bit operator==(nbr lhs, nbr rhs){
            bit result{-1};
            for (int i=0; i<16; i++){
                if (lhs.s[i].v == -1 && rhs.s[i].v == -1) continue;
                if (lhs.s[i].v == -1) lhs.s[i] = zero;
                if (rhs.s[i].v == -1) rhs.s[i] = zero;
                bit eq = (lhs.s[i] == rhs.s[i]);
                if (result.v == -1) result = eq;
                else result = result & eq;
            }
            return result;
        }
    void erase_deps(int la, int lb, vector<nbr> &results){
        vector<int> act(a.size());
        for (int i=0; i<la + lb; i++) act[i] = 1;
        for (const nbr &v: results){
            for (bit x: v.s){
                if (x.v == -1) x = zero;
                act[x.v] = 1;
            }
        }

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

        int cnt = 0;
        vector<bit_construct> s;
        for (int i=0; i<a.size(); i++){
            if (act[i] == 0) continue;
            act[i] = cnt++;
            s.push_back({a[i].p, bit{act[a[i].x.v]}, bit{act[a[i].y.v]}});
        }
        a = move(s);
        for (nbr &r: results){
            for (bit &v: r.s) v.v = act[v.v];
        }
    }
    void init(int la, int lb){
        a.resize(la + lb);
        zero = create_gate(OP_ZERO, bit{0}, bit{0});
        one = create_gate(OP_ONE, bit{0}, bit{0});
    }
    int output(int la, int lb, int ops[], int opers[][2], int outputs[][16], vector<nbr> result){
        erase_deps(la, lb, result);
        for (int i=la+lb; i<a.size(); i++){
            ops[i] = a[i].p;
            opers[i][0] = a[i].x.v;
            opers[i][1] = a[i].y.v;
        }
        for (int i=0; i<result.size(); i++){
            for (int j=0; j<16; j++){
                outputs[i][j] = result[i].s[j].v;
            }
        }
        return a.size();
    }
    int run(int la, int lb, int ops[], int opers[][2], int outputs[][16]){
        init(la, lb);
        
        int n = la / 32, ptr = 0;

        vector<nbr> aweight(n);
        for (int i=0; i<n; i++){
            aweight[i] = nbr(ptr);
            ptr += 16;
        }

        vector<nbr> aposi(n);
        for (int i=0; i<n; i++){
            aposi[i] = nbr(ptr);
            ptr += 16;
        }
        assert(ptr == la);

        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 = ptr++;
            }
        }
        assert(ptr == la + lb);

        vector<nbr> 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<nbr> result(n);
        for (int i=0; i<n; i++){
            for (int j=0; j<n; j++){
                nbr jn; jn.init_value(j);
                result[i] = result[i] + (tresult[j] & (aposi[i] == jn));
            }
        }

        return output(la, lb, ops, opers, outputs, result);
    }
}
// TODO: erase deps

// 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_ns::run(la, lb, operations, operands, outputs_circuit);
}

Compilation message

abc.cpp: In function 'int bob(int, const char (*)[5], const char (*)[5], bool*)':
abc.cpp:102:20: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  102 |     for (int i=0; i<pp.size(); i++){
      |                   ~^~~~~~~~~~
abc.cpp:103:24: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  103 |         for (int j=0; j<pp.size(); j++){
      |                       ~^~~~~~~~~~
abc.cpp: In constructor 'circuit_ns::nbr::nbr()':
abc.cpp:139:35: warning: 'void* memset(void*, int, size_t)' writing to an object of non-trivial type 'struct circuit_ns::bit'; use assignment instead [-Wclass-memaccess]
  139 |             memset(s, -1, sizeof s);
      |                                   ^
abc.cpp:111:12: note: 'struct circuit_ns::bit' declared here
  111 |     struct bit{
      |            ^~~
abc.cpp: In function 'circuit_ns::nbr circuit_ns::operator+(const circuit_ns::nbr&, const circuit_ns::nbr&)':
abc.cpp:171:21: warning: variable 'five' set but not used [-Wunused-but-set-variable]
  171 |                 bit five = result.s[ptr] = four ^ three;
      |                     ^~~~
abc.cpp: In function 'void circuit_ns::erase_deps(int, int, std::vector<circuit_ns::nbr>&)':
abc.cpp:262:24: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<circuit_ns::bit_construct>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  262 |         for (int i=0; i<a.size(); i++){
      |                       ~^~~~~~~~~
abc.cpp: In function 'int circuit_ns::output(int, int, int*, int (*)[2], int (*)[16], std::vector<circuit_ns::nbr>)':
abc.cpp:279:28: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<circuit_ns::bit_construct>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  279 |         for (int i=la+lb; i<a.size(); i++){
      |                           ~^~~~~~~~~
abc.cpp:284:24: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<circuit_ns::nbr>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  284 |         for (int i=0; i<result.size(); i++){
      |                       ~^~~~~~~~~~~~~~
# 결과 실행 시간 메모리 Grader output
1 Runtime error 6 ms 1552 KB Execution killed with signal 6
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Runtime error 6 ms 1552 KB Execution killed with signal 6
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Runtime error 6 ms 1552 KB Execution killed with signal 6
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 12 ms 9204 KB Correct!
2 Correct 39 ms 9660 KB Correct!
3 Correct 47 ms 10360 KB Correct!
# 결과 실행 시간 메모리 Grader output
1 Correct 12 ms 9204 KB Correct!
2 Correct 39 ms 9660 KB Correct!
3 Correct 47 ms 10360 KB Correct!
4 Correct 41 ms 11284 KB Correct!
5 Correct 51 ms 10324 KB Correct!
# 결과 실행 시간 메모리 Grader output
1 Correct 12 ms 9204 KB Correct!
2 Correct 39 ms 9660 KB Correct!
3 Correct 47 ms 10360 KB Correct!
4 Correct 41 ms 11284 KB Correct!
5 Correct 51 ms 10324 KB Correct!
6 Correct 39 ms 9376 KB Correct!
7 Correct 66 ms 15256 KB Correct!
# 결과 실행 시간 메모리 Grader output
1 Runtime error 44 ms 9848 KB Execution killed with signal 11
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Runtime error 44 ms 9848 KB Execution killed with signal 11
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Runtime error 6 ms 1552 KB Execution killed with signal 6
2 Halted 0 ms 0 KB -