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 "abc.h"
#include <bits/stdc++.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
// Alice
int // returns la
alice(
/* in */ const int n,
/* in */ const char names[][5],
/* in */ const unsigned short numbers[],
/* out */ bool outputs_alice[]
) {
if (n==1){
//output numbers[0]
for(int i=0;i<16;i++){
outputs_alice[i] = numbers[0] & (1<<i);
}
return 16;
} else if (n<=30){
vector<string> stringss;
map<string,int> order;
for(int i=0;i<n;i++) {
stringss.push_back(names[i]);
order[names[i]] = i;
}
sort(stringss.begin(),stringss.end());
map<int, string> position; //the person at position
map<int,int> nums; //the number of person at position
for(int i=0;i<n;i++){
position[i] = stringss[i];
nums[i] = numbers[order[position[i]]];
}
for(int j=0;j<n;j++){
//cout << position[j] << ": " << nums[j] << ", " << j << "\n";
for(int i=0;i<16;i++){
outputs_alice[21*j+i] = nums[j] & (1<<i);
}
int poss = order[position[j]];
for(int i=16;i<21;i++){
outputs_alice[21*j+i] = poss & (1<<(i-16));
}
}
return 21*n;
}
}
// Bob
int // returns lb
bob(
/* in */ const int m,
/* in */ const char senders[][5],
/* in */ const char recipients[][5],
/* out */ bool outputs_bob[]
) {
/*
outputs_bob[0] = 1;
outputs_bob[1] = 1;
outputs_bob[2] = 0;
*/
//output m
bool s1 = true;
if (m>1){
for(int i=0;i<5;i++){
if (senders[0][i]!=senders[1][i]){
s1 = false;
break;
}
}
for(int i=0;i<5;i++){
if (recipients[0][i]!=recipients[1][i]){
s1 = false;
break;
}
}
}
if (s1){
for(int i=0;i<10;i++){
outputs_bob[i] = m & (1<<i);
}
return 10;
} else {
set<string> stringss;
for(int e=0;e<m;e++){
stringss.insert(senders[e]);
stringss.insert(recipients[e]);
}
int n = (int)stringss.size();
int count = 0;
map<string,int> poss;
for(auto s : stringss){
poss[s] = count;
count++;
}
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
outputs_bob[n*i+j] = 0;
}
}
//for all edges, mark at the receiving end
for(int e=0;e<m;e++){
int s = poss[senders[e]];
int r = poss[recipients[e]];
//cout << senders[e] << " (" << poss[senders[e]] << ") -> " << recipients[e] << " (" << poss[recipients[e]] << ")\n";
outputs_bob[n*r+s] = 1;
}
return n*n;
}
}
struct gate {
int p;
int x0,x1;
};
vector<gate> bitShiftBlock(int pos, int shift, int left, int size, int determinant=-1){ //if determinant output = 0, block=0
vector<gate> block;
//the first shift are all 0
for(int i=0;i<shift;i++){
block.push_back({0,0,1});
}
//the remaining work from the left
for(int i=0;i<size-shift;i++){
if (determinant==-1){
block.push_back({8,left+i,left+i});
} else block.push_back({8,left+i,determinant});
}
return block;
}
//sum block
//maybe some can be saved here
// {block of length size starting at left}{block of length size starting at left2}{stuff.....sum of two blocks}
vector<gate> sumBlock(int pos, int left, int left2, int size){
vector<gate> block;
vector<gate> endBlock;
//first gate is sum0: xor
int at = pos;
block.push_back({6,left,left2});
endBlock.push_back({10,at,0});
at++;
//next gate is carry0: and
block.push_back({8,left,left2});
at++;
//create remaining using full adders
for(int i=1;i<size;i++){
//D is xor of things
block.push_back({6,left+i,left2+i});
at++; // D is at-1, Cin is at-2
//E is D AND Cin
block.push_back({8,at-1,at-2});
at++; //E is at-1, D is at-2, Cin is at-3
//F is A AND B
block.push_back({8,left+i,left2+i});
at++; //F is at-1, E is at-2, D is at-3, Cin is at-4
//S is D XOR Cin
block.push_back({6,at-3,at-4});
endBlock.push_back({10,at,0});
at++; //F is at-2, E is at-3, D is at-4, Cin is at-5
//Cout is F XOR E
block.push_back({6,at-2,at-3});
at++;
}
//add endBlock to block
for(auto a : endBlock){
block.push_back(a);
}
return block;
}
//sort block
//{block of length size starting at left1}{block of length size starting at left2}{stuff...2 blocks in order smallest to largest}
vector<gate> sortBlock(int pos, int left1, int left2, int size){
vector<gate> block;
stack<gate> smallBlock;
stack<gate> bigBlock;
int at = pos;
block.push_back({0,0,1}); //Uin is initially zero
block.push_back({0,0,1}); //L1in is initially zero
at += 2; //Uin is at-2, L1in is at-1
for(int i=1;i<=size;i++){
//define B1 and B2
int B1 = left1+size-i;
int B2 = left2+size-i;
//define Uin and L1in
int Uin = at-2;
int L1in = at-1;
block.push_back({8,B1,L1in});
int a = at++;
block.push_back({2,B2,L1in});
int b = at++;
block.push_back({14,a,b});
int c = at++;
block.push_back({8,Uin,c});
int d = at++;
block.push_back({8,B1,B2});
int e = at++;
block.push_back({14,e,d});
int kk = at++;
smallBlock.push({8,kk,kk});
block.push_back({14,B1,B2});
int f = at++;
block.push_back({2,f,kk});
int g = at++;
bigBlock.push({14,e,g});
block.push_back({6,B1,B2});
int h = at++;
block.push_back({4,B1,B2});
int j = at++;
block.push_back({4,Uin,j});
int k = at++;
block.push_back({14,Uin,h});
at++;
block.push_back({14,L1in,k});
at++;
}
while(!smallBlock.empty()){
block.push_back({smallBlock.top()});
smallBlock.pop();
}
while(!bigBlock.empty()){
block.push_back({bigBlock.top()});
bigBlock.pop();
}
return block;
}
// 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]
) {
//first bits are input
int L = la+lb;
int n = la/21;
if (L==26){
//start by adding null block of zeros
for(int i=0;i<16;i++){
operations[L] = 0;
operands[L][0] = 0;
operands[L][1] = 0;
L++;
}
//do all things
for(int i=0;i<10;i++){
//add the bitshift block at L
vector<gate> block = bitShiftBlock(L,i,0,16,16+i);
for(auto a : block){
operations[L] = a.p;
operands[L][0] = a.x0;
operands[L][1] = a.x1;
L++;
}
//add the sum block at L
vector<gate> block2 = sumBlock(L,L-32,L-16,16);
for(auto a : block2){
operations[L] = a.p;
operands[L][0] = a.x0;
operands[L][1] = a.x1;
L++;
}
}
//answer is just last 16 bits
for(int j=0;j<16;j++){
outputs_circuit[0][j] = L-16+j;
}
} else {
vector<int> resultsStarts;
//solve person by person
for(int p=0;p<n;p++){
//add null block of zeros
for(int i=0;i<16;i++){
operations[L] = 0;
operands[L][0] = 0;
operands[L][1] = 0;
L++;
}
//then, for every other person, copy over their number if they sent a thing to p (0 otherwise), and add to running total
for(int q=0;q<n;q++){
//add the bitshift block at L
vector<gate> block = bitShiftBlock(L,0,21*q,16,la+n*p+q);
for(auto a : block){
operations[L] = a.p;
operands[L][0] = a.x0;
operands[L][1] = a.x1;
L++;
}
//keep running total
//add the sum block at L
vector<gate> block2 = sumBlock(L,L-32,L-16,16);
for(auto a : block2){
operations[L] = a.p;
operands[L][0] = a.x0;
operands[L][1] = a.x1;
L++;
}
}
//result for this person is last 16 bits
//printf("%d\n",L-16);
resultsStarts.push_back(L-16);
/*
for(int j=0;j<16;j++){
outputs_circuit[p][j] = L-16+j;
}
*/
}
//shift all results to end, including number from alice
for(int i=0;i<n;i++){
vector<gate> block = bitShiftBlock(L,0,resultsStarts[i],16);
for(auto a : block){
operations[L] = a.p;
operands[L][0] = a.x0;
operands[L][1] = a.x1;
L++;
}
vector<gate> block2 = bitShiftBlock(L,0,21*i+16,5);
for(auto a : block2){
operations[L] = a.p;
operands[L][0] = a.x0;
operands[L][1] = a.x1;
L++;
}
}
//complete N-1 Passes
for(int pass=n-2;pass>=0;pass--){
for(int firstSwap = 0;firstSwap<=pass;firstSwap++){
//define start of previous
int prevStart = L - 21*n;
//create the block with the appropriate swapped version
vector<gate> swappedBlock = sortBlock(L,prevStart+21*firstSwap,prevStart+21*(firstSwap+1),21);
for(auto a : swappedBlock){
operations[L] = a.p;
operands[L][0] = a.x0;
operands[L][1] = a.x1;
L++;
}
int sortedStart = L-21*2;
//create block to add all before swapped part
vector<gate> b1 = bitShiftBlock(L,0,prevStart,21*firstSwap);
for(auto a : b1){
operations[L] = a.p;
operands[L][0] = a.x0;
operands[L][1] = a.x1;
L++;
}
//create block to add swapped part
vector<gate> b2 = bitShiftBlock(L,0,sortedStart,21*2);
for(auto a : b2){
operations[L] = a.p;
operands[L][0] = a.x0;
operands[L][1] = a.x1;
L++;
}
//create block to add all after swapped part
vector<gate> b3 = bitShiftBlock(L,0,prevStart+21*(firstSwap+2),21*(n-(firstSwap+2)));
for(auto a : b3){
operations[L] = a.p;
operands[L][0] = a.x0;
operands[L][1] = a.x1;
L++;
}
}
}
/*
*/
//results are then sorted
for(int p=0;p<n;p++){
for(int j=0;j<16;j++){
outputs_circuit[p][j] = L-21*n + 21*p + j;
}
}
}
//printf("%d\n",L);
return L;
/*
//start by adding null block of zeros
for(int i=0;i<16;i++){
operations[L] = 0;
operands[L][0] = 0;
operands[L][1] = 0;
L++;
}
//do all things
for(int i=0;i<10;i++){
//add the bitshift block at L
vector<gate> block = bitShiftBlock(L,i,0,16,16+i);
for(auto a : block){
operations[L] = a.p;
operands[L][0] = a.x0;
operands[L][1] = a.x1;
L++;
}
//add the sum block at L
vector<gate> block2 = sumBlock(L,L-32,L-16,16);
for(auto a : block2){
operations[L] = a.p;
operands[L][0] = a.x0;
operands[L][1] = a.x1;
L++;
}
}
//answer is just last 16 bits
for(int j=0;j<16;j++){
outputs_circuit[0][j] = L-16+j;
}
*/
//printf("%d\n",L);
/*
operations[5] = 8;
operations[6] = 14;
operands[5][0] = 0; operands[5][1] = 4;
operands[6][0] = 2; operands[6][1] = 5;
int final_results[] = {20000, 0, 24464};
for(int i = 0; i < 3; ++i)
for(int j = 0; j < 16; ++j)
outputs_circuit[i][j] = 5 + (final_results[i] >> j & 1);
return 7;
*/
}
Compilation message (stderr)
abc.cpp: In function 'int alice(int, const char (*)[5], const short unsigned int*, bool*)':
abc.cpp:67:1: warning: control reaches end of non-void function [-Wreturn-type]
67 | }
| ^
# | 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... |