Submission #438149

# Submission time Handle Problem Language Result Execution time Memory
438149 2021-06-27T16:34:36 Z CyanForces Bit Shift Registers (IOI21_registers) C++17
35 / 100
2 ms 632 KB
#include <bits/stdc++.h>
using namespace std;

#define rep(i, a, b) for(int i = a; i < (b); ++i)
#define trav(a, x) for(auto& a : x)
#define all(x) begin(x), end(x)
#define sz(x) (int)(x).size()
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;

#include "registers.h"

int s, n, k, q;
int ops = 0;
vector<bool> negOne(2000);
vector<bool> signBit(2000);
vector<bool> oneNum(2000);

const int negOneIndex = 99;
const int signBitIndex = 98;
const int oneNumIndex = 97;
const int workRegister = 96;

void spread() {
	for(int i = 0; i < n; i++) {
		append_and(workRegister, 0, oneNumIndex);
		ops++;
		if (i != n-1) {
			append_left(oneNumIndex, oneNumIndex, k+2);
			ops++;
			append_left(0, 0, 2);
			ops++;
		}
		append_or(1, 1, workRegister);
		ops++;
	}
}

void divide() {
	int leftNumbers = (n+1) / 2;
	append_move(2, 1);
	ops++;
	append_right(2, 2, leftNumbers * (k+2));
	ops++;
	vector<bool> tempExtra(2000);
	rep(i,0,2000) {
		tempExtra[i] = (n-leftNumbers)*(k+2) <= i && i < (n-leftNumbers+1)*(k+2)-1;
	}
	append_store(3, tempExtra);
	ops++;
	append_or(2, 2, 3);
	ops++;
}

void spreadSigns(int d) {
	append_move(workRegister, 0);
	ops++;
	append_right(workRegister, workRegister, d);
	ops++;
	append_or(0, 0, workRegister);
	ops++;
}

void combine() {
	append_store(0, negOne);
	ops++;
	append_add(0, 0, 2); // b-1
	ops++;
	append_not(0, 0); // !(b-1)
	ops++;
	append_add(0, 0, 1); // a-b
	ops++;

	append_and(0, 0, signBitIndex);
	ops++;
	rep(_,0,k+1) spreadSigns(1);
	//int curr = 1;
	//while(curr*2 < k+2) {
	//	spreadSigns(curr);
	//	curr *= 2;
	//}
	//spreadSigns(k+2 - curr);

	append_not(workRegister, 0);
	ops++;
	// registry 0 contains zeros if a >= b, else 1
	// => registry 0 contains a >= b
	// => workRegister contains a < b
	append_and(0, 0, 1);
	ops++;
	append_and(workRegister, workRegister, 2);
	ops++;

	append_xor(1, 1, 2);
	// register 0 = xor(a, b)
	ops++;
	append_xor(2, 0, workRegister);
	ops++;
	// register 2 = max(a, b)
	append_xor(1, 1, 2);
	ops++;
}

void print() {
	rep(i,0,3) append_print(i);
}

void findMin() {
	spread();
	while(n > 1) {
		//print();
		divide();
		//print();
		combine();
		//print();
		n = (n+1) / 2;
	}
	//print();
	append_move(0, 1);
	ops++;
}

void unspread() {
	vector<bool> empty(2000);
	append_store(0, empty);
	int shiftAmount = n-1;

	for(int i = n-1; i >= 0; i--) {
		cerr << "i = " << i << endl;
		cerr << "ops = " << ops << endl;
		append_and(workRegister, 1, oneNumIndex);
		ops++;
		append_right(workRegister, workRegister, 2*i);
		ops++;
		append_right(oneNumIndex, oneNumIndex, k+2);
		ops++;
		if (shiftAmount > 0) {
			append_right(workRegister, workRegister, shiftAmount * k);
		}
		else {
			append_left(workRegister, workRegister, -shiftAmount * k);
		}
		shiftAmount -= 2;

		append_or(0, 0, workRegister);
		ops++;
	}

	//append_store(oneNumIndex, oneNum);
	//append_store(1, empty);
	//spread();
	//print();
}

void stupidSort() {
	spread();

	vector<bool> tempExtra(2000);
	rep(i,0,2000) {
		tempExtra[i] = i < k;
	}
	append_store(75, tempExtra);
	ops++;

	vector<bool> takeFirst(2000), takeSecond(2000);
	rep(i,0,2000) {
		int temp = (i / (k+2)) % 2;
		if (temp == 0) takeFirst[i] = 1;
		else takeSecond[i] = 1;
	}
	append_store(50, takeFirst);
	ops++;
	append_store(51, takeSecond);
	ops++;
	cerr << "n = " << n << endl;
	print();
	rep(i,0,n+3) {
		print();
		cerr << "i = " << i << ", ops = " << ops << endl;
		append_move(2, 1);
		ops++;
		append_left(2, 2, k+2);
		ops++;
		append_xor(2, 2, 75);
		ops++;
		combine();
		print();

		cerr << "i = " << i << ", ops = " << ops << endl;
		if (i % 2 == 0) {
			append_and(1, 1, 50);
			ops++;
			append_and(2, 2, 50);
			ops++;
			append_right(2, 2, k+2);
			ops++;
		}
		else {
			append_and(1, 1, 51);
			ops++;
			append_and(2, 2, 51);
			ops++;
			append_right(2, 2, k+2);
			ops++;
		}
		print();
		append_or(1, 1, 2);
		ops++;
		append_print(52);
	}

	unspread();
}

void construct_instructions(int _s, int _n, int _k, int _q) {
	s = _s;
	n = _n;
	k = _k;
	q = _q;
	int a = 0;
	int b = k+2;
	while(b < 2000) {
		for(int j = a; j < b; j++) negOne[j] = j != b-1;
		a = b;
		b += k+2;
	}
	for(int i = 0; i < 2000; i++) {
		signBit[i] = i % (k+2) == k+1;
		oneNum[i] = i < k;
	}
	append_store(negOneIndex, negOne);
	ops++;
	append_store(signBitIndex, signBit);
	ops++;
	append_store(oneNumIndex, oneNum);
	ops++;

	if (s == 0) {
		findMin();
	}
	else {
		stupidSort();
	}
	assert(ops <= q);
}
# Verdict Execution time Memory Grader output
1 Correct 1 ms 204 KB Output is correct
# Verdict Execution time Memory Grader output
1 Incorrect 1 ms 204 KB Wrong answer detected in grader
# Verdict Execution time Memory Grader output
1 Correct 1 ms 204 KB Output is correct
2 Correct 1 ms 332 KB Output is correct
3 Correct 2 ms 332 KB Output is correct
4 Correct 1 ms 332 KB Output is correct
# Verdict Execution time Memory Grader output
1 Incorrect 1 ms 204 KB Wrong answer detected in grader
2 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Correct 2 ms 332 KB Output is correct
2 Correct 2 ms 332 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 2 ms 332 KB Output is correct
2 Correct 2 ms 332 KB Output is correct
3 Incorrect 2 ms 632 KB Wrong answer detected in grader
4 Halted 0 ms 0 KB -