This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#include <bits/stdc++.h>
#include "abc.h"
using namespace std;
// you may find the definitions useful
const int OP_ZERO = 0; // f(OP_ZERO, x0, x1) = 0
const int OP_NOR = 1; // f(OP_NOR, x0, x1) = !(x0 || x1)
const int OP_GREATER = 2; // f(OP_GREATER, x0, x1) = (x0 > x1)
const int OP_NOT_X1 = 3; // f(OP_NOT_X1, x0, x1) = !x1
const int OP_LESS = 4; // f(OP_LESS, x0, x1) = (x0 < x1)
const int OP_NOT_X0 = 5; // f(OP_NOT_X0, x0, x1) = !x0
const int OP_XOR = 6; // f(OP_XOR, x0, x1) = (x0 ^ x1)
const int OP_NAND = 7; // f(OP_NAND, x0, x1) = !(x0 && x1)
const int OP_AND = 8; // f(OP_AND, x0, x1) = (x0 && x1)
const int OP_EQUAL = 9; // f(OP_EQUAL, x0, x1) = (x0 == x1)
const int OP_X0 = 10; // f(OP_X0, x0, x1) = x0
const int OP_GEQ = 11; // f(OP_GEQ, x0, x1) = (x0 >= x1)
const int OP_X1 = 12; // f(OP_X1, x0, x1) = x1
const int OP_LEQ = 13; // f(OP_LEQ, x0, x1) = (x0 <= x1)
const int OP_OR = 14; // f(OP_OR, x0, x1) = (x0 || x1)
const int OP_ONE = 15; // f(OP_ONE, x0, x1) = 1
int encode(string s) {
int res = 0;
for (auto c: s) {
res = res * 26 + (c - 'a');
}
int pw = 1;
for (int i = 1; i <= (int)s.size() - 1; i++) {
pw = pw * 26;
res += pw;
}
return res;
}
vector<int> build(vector<int> a) {
int n = a.size();
if (n <= 1) {
return vector<int>();
}
vector<int> pos(n);
for (int i = 0; i < n; i++) {
pos[a[i]] = i;
}
vector<vector<pair<int, int>>> adj(n);
vector<int> swap1(n / 2, -1);
vector<int> swap2(n / 2, -1);
for (int i = 0; i < n / 2; i++) {
int x = pos[i];
int y = pos[n / 2 + i];
if (n % 2 == 1 && (x == n - 1 || y == n - 1)) {
continue;
}
int u = (x < n / 2 ? x : x - n / 2);
int v = (y < n / 2 ? y : y - n / 2);
int w = (x < n / 2) ^ (y < n / 2) ^ 1;
adj[u].emplace_back(v, w);
adj[v].emplace_back(u, w);
}
if (n % 2 == 1 && pos[n - 1] != n - 1) {
int cur = (pos[n - 1] < n / 2 ? pos[n - 1] : pos[n - 1] - n / 2);
swap1[cur] = (pos[n - 1] < n / 2);
while (true) {
bool found = false;
for (auto e: adj[cur]) {
int nxt = e.first;
int w = e.second;
if (swap1[nxt] == -1) {
swap1[nxt] = swap1[cur] ^ w;
cur = nxt;
found = true;
break;
}
}
if (!found) {
break;
}
}
}
for (int i = 0; i < n / 2; i++) {
if (swap1[i] == -1) {
int cur = i;
swap1[cur] = 0;
while (true) {
bool found = false;
for (auto e: adj[cur]) {
int nxt = e.first;
int w = e.second;
if (swap1[nxt] == -1) {
swap1[nxt] = swap1[cur] ^ w;
cur = nxt;
found = true;
break;
}
}
if (!found) {
break;
}
}
}
}
vector<int> al(a.begin(), a.begin() + n / 2);
vector<int> ar(a.begin() + n / 2, a.end());
for (int i = 0; i < n / 2; i++) {
if (swap1[i]) {
swap(al[i], ar[i]);
}
}
for (int i = 0; i < n / 2; i++) {
if (al[i] < n / 2) {
swap2[al[i]] = 0;
}
else {
al[i] -= n / 2;
swap2[al[i]] = 1;
}
}
for (int i = 0; i < n - n / 2; i++) {
if (ar[i] >= n / 2) {
ar[i] -= n / 2;
}
}
vector<int> fl = build(al);
vector<int> fr = build(ar);
vector<int> res(swap1.begin(), swap1.end());
res.insert(res.end(), fl.begin(), fl.end());
res.insert(res.end(), fr.begin(), fr.end());
res.insert(res.end(), swap2.begin(), swap2.end());
return res;
}
int calc(int n) {
if (n <= 1) {
return 0;
}
return calc(n / 2) + calc(n - n / 2) + (n / 2) * 2;
}
// 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, int>> order(n);
for (int i = 0; i < n; i++) {
order[i] = make_pair(encode(names[i]), i);
}
sort(order.begin(), order.end());
for (int i = 0; i < n; i++) {
for (int j = 0; j < 19; j++) {
outputs_alice[i * 35 + j] = (order[i].first >> j) & 1;
}
for (int j = 0; j < 16; j++) {
outputs_alice[i * 35 + 19 + j] = (numbers[order[i].second] >> j) & 1;
}
}
vector<int> perm(n);
for (int i = 0; i < n; i++) {
perm[i] = order[i].second;
}
vector<int> flag = build(perm);
int sz = flag.size();
for (int i = 0; i < sz; i++) {
outputs_alice[n * 35 + i] = flag[i];
}
return n * 35 + sz;
}
// 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>> order1(m);
for (int i = 0; i < m; i++) {
order1[i] = make_pair(encode(recipients[i]), encode(senders[i]));
}
sort(order1.begin(), order1.end());
vector<pair<pair<int, int>, int>> order2(m);
for (int i = 0; i < m; i++) {
order2[i] = make_pair(make_pair(order1[i].second, order1[i].first), i);
}
sort(order2.begin(), order2.end());
for (int i = 0; i < m; i++) {
for (int j = 0; j < 19; j++) {
outputs_bob[i * 38 + j] = (order2[i].first.first >> j) & 1;
}
for (int j = 0; j < 19; j++) {
outputs_bob[i * 38 + 19 + j] = (order2[i].first.second >> j) & 1;
}
}
vector<int> perm(m);
for (int i = 0; i < m; i++) {
perm[i] = order2[i].second;
}
vector<int> flag = build(perm);
int sz = flag.size();
for (int i = 0; i < sz; i++) {
outputs_bob[m * 38 + i] = flag[i];
}
return m * 38 + sz;
}
int *operations;
int (*operands)[2];
int ZERO_GATE;
int ONE_GATE;
int gate_cnt;
int gate(int op, int x, int y) {
operations[gate_cnt] = op;
operands[gate_cnt][0] = x;
operands[gate_cnt][1] = y;
return gate_cnt++;
}
pair<int, int> add(int x, int y, int z) {
int sum1 = gate(OP_XOR, x, y);
int rem1 = gate(OP_AND, x, y);
int sum2 = gate(OP_XOR, sum1, z);
int rem2 = gate(OP_AND, sum1, z);
return make_pair(sum2, gate(OP_OR, rem1, rem2));
}
vector<int> add(vector<int> num1, vector<int> num2) {
vector<int> res(16);
int rem = ZERO_GATE;
for (int i = 0; i < 16; i++) {
auto p = add(num1[i], num2[i], rem);
res[i] = p.first;
rem = p.second;
}
return res;
}
vector<int> mul(vector<int> num, int x) {
vector<int> res(16);
for (int i = 0; i < 16; i++) {
res[i] = gate(OP_AND, num[i], x);
}
return res;
}
vector<int> mul_flip(vector<int> num, int x) {
vector<int> res(16);
for (int i = 0; i < 16; i++) {
res[i] = gate(OP_GREATER, num[i], x);
}
return res;
}
vector<int> _xor(vector<int> num1, vector<int> num2) {
vector<int> res(16);
for (int i = 0; i < 16; i++) {
res[i] = gate(OP_XOR, num1[i], num2[i]);
}
return res;
}
struct event {
int type;
bool fake;
vector<int> name1, name2, val;
event(): type(-1), fake(true) {};
};
vector<event> events;
vector<pair<int, int>> swaps;
vector<int> flag;
void build(int lt, int rt) {
int n = rt - lt + 1;
if (n <= 1) {
return;
}
for (int i = 0; i < n / 2; i++) {
swaps.emplace_back(lt + i, lt + n / 2 + i);
}
build(lt, lt + n / 2 - 1);
build(lt + n / 2, rt);
for (int i = 0; i < n / 2; i++) {
swaps.emplace_back(lt + i, lt + n / 2 + i);
}
}
void swap(int &x, int &y, int f) {
int z = gate(OP_AND, gate(OP_XOR, x, y), f);
x = gate(OP_XOR, x, z);
y = gate(OP_XOR, y, z);
}
int comp(int x, int y) {
if (events[y].fake) {
return ZERO_GATE;
}
if (events[x].fake) {
return ONE_GATE;
}
int equal = ONE_GATE;
int res = ZERO_GATE;
for (int i = 18; i >= 0; i--) {
res = gate(OP_OR, res, gate(OP_AND, equal, gate(OP_GREATER, events[x].name1[i], events[y].name1[i])));
equal = gate(OP_AND, equal, gate(OP_EQUAL, events[x].name1[i], events[y].name1[i]));
}
res = gate(OP_OR, res, gate(OP_AND, equal, gate(OP_GREATER, events[x].type, events[y].type)));
equal = gate(OP_AND, equal, gate(OP_EQUAL, events[x].type, events[y].type));
return res;
}
void shuffle() {
int sz = swaps.size();
for (int i = 0; i < sz; i++) {
int x = swaps[i].first;
int y = swaps[i].second;
if (flag[i] == -1) {
flag[i] = comp(x, y);
}
if (flag[i] == ZERO_GATE) {
continue;
}
if (flag[i] == ONE_GATE) {
swap(events[x], events[y]);
continue;
}
for (int j = 0; j < 19; j++) {
swap(events[x].name1[j], events[y].name1[j], flag[i]);
swap(events[x].name2[j], events[y].name2[j], flag[i]);
}
for (int j = 0; j < 16; j++) {
swap(events[x].val[j], events[y].val[j], flag[i]);
}
swap(events[x].type, events[y].type, flag[i]);
}
}
void merge(int x, int y, int step) {
if (x + step == y) {
swaps.emplace_back(x, y);
return;
}
merge(x, y, step * 2);
merge(x + step, y + step, step * 2);
x += step;
while (x + step < 2048) {
swaps.emplace_back(x, x + step);
x += step * 2;
}
}
// 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]
) {
operations = _operations;
operands = _operands;
gate_cnt = la + lb;
ZERO_GATE = gate(OP_ZERO, 0, 0);
ONE_GATE = gate(OP_ONE, 0, 0);
int n = 0;
while (n * 35 + calc(n) < la) {
n++;
}
int m = 0;
while (m * 38 + calc(m) < lb) {
m++;
}
events.resize(2048);
for (int i = 0; i < n; i++) {
events[i].name1.resize(19);
events[i].name2.resize(19);
events[i].val.resize(16);
for (int j = 0; j < 19; j++) {
events[i].name1[j] = i * 35 + j;
events[i].name2[j] = i * 35 + j;
}
for (int j = 0; j < 16; j++) {
events[i].val[j] = i * 35 + 19 + j;
}
events[i].type = ZERO_GATE;
events[i].fake = false;
}
for (int i = 0; i < m; i++) {
events[1024 + i].name1.resize(19);
events[1024 + i].name2.resize(19);
events[1024 + i].val.resize(16, ZERO_GATE);
for (int j = 0; j < 19; j++) {
events[1024 + i].name1[j] = la + i * 38 + j;
events[1024 + i].name2[j] = la + i * 38 + 19 + j;
}
events[1024 + i].type = ONE_GATE;
events[1024 + i].fake = false;
}
merge(0, 1024, 1);
flag.resize(swaps.size(), -1);
shuffle();
vector<int> cur(16, ZERO_GATE);
for (int i = 0; i < n + m; i++) {
cur = _xor(cur, mul_flip(_xor(cur, events[i].val), events[i].type));
events[i].val = cur;
swap(events[i].name1, events[i].name2);
}
reverse(swaps.begin(), swaps.end());
reverse(flag.begin(), flag.end());
shuffle();
swaps.clear();
flag.clear();
build(1024, 1024 + m - 1);
flag.resize(swaps.size());
for (int i = 0; i < (int)flag.size(); i++) {
flag[i] = la + m * 38 + i;
}
shuffle();
swaps.clear();
flag.clear();
merge(0, 1024, 1);
flag.resize(swaps.size(), -1);
shuffle();
cur.clear();
cur.resize(16, ZERO_GATE);
for (int i = n + m - 1; i >= 0; i--) {
swap(cur, events[i].val);
cur = mul(add(cur, events[i].val), events[i].type);
}
reverse(swaps.begin(), swaps.end());
reverse(flag.begin(), flag.end());
shuffle();
swaps.clear();
flag.clear();
build(0, n - 1);
flag.resize(swaps.size());
for (int i = 0; i < (int)flag.size(); i++) {
flag[i] = n * 35 + i;
}
shuffle();
for (int i = 0; i < n; i++) {
for (int j = 0; j < 16; j++) {
outputs_circuit[i][j] = events[i].val[j];
}
}
return gate_cnt;
}
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |