Submission #304369

# Submission time Handle Problem Language Result Execution time Memory
304369 2020-09-21T08:15:23 Z ecnerwala Counting Mushrooms (IOI20_mushrooms) C++17
0 / 100
2000 ms 90580 KB
#include "mushrooms.h"

#include <bits/stdc++.h>

namespace {

enum class MOVE_TYPE {
	NONE,
	AxAx,
	AxAxAxAx,
	xAx_xBx,
};

std::pair<int, MOVE_TYPE> get_max_cnt(int ka, int kb, int q) {
	if (q == 0) return {0, MOVE_TYPE::AxAxAxAx};

	if (ka < kb) std::swap(ka, kb);
	assert(ka >= kb);

	static std::map<std::tuple<int, int, int>, std::pair<int, MOVE_TYPE>> mem;
	auto it = mem.find({ka, kb, q});
	if (it != mem.end()) return it->second;

	std::pair<int, MOVE_TYPE> ans = {0, MOVE_TYPE::AxAxAxAx};

	// AxAx
	if (ka >= 2 || kb >= 2) {
		ans = std::max(ans,
			{
				2 + std::min({
					get_max_cnt(ka+2, kb+0, q-1).first,
					get_max_cnt(ka+1, kb+1, q-1).first,
					get_max_cnt(ka+0, kb+2, q-1).first,
				}), MOVE_TYPE::AxAx
			}
		);
	}

	// AxAxAxAxAx
	ans = std::max(ans, 
		{
			std::max(ka, kb) + std::min(get_max_cnt(ka+1, kb, q-1).first, get_max_cnt(ka, kb+1, q-1).first), MOVE_TYPE::AxAxAxAx
		}
	);

	// xAxxAxxAx - xBxxBxxBx
	if (q >= 2 && std::min(ka, kb) >= 1) {
		ans = std::max(ans,
			{ std::min(ka, kb) * 2 + get_max_cnt(ka, kb, q-2).first, MOVE_TYPE::xAx_xBx }
		);
	}

	return mem[{ka, kb, q}] = ans;
}

int get_max_cnt(int q) {
	return get_max_cnt(1, 0, q).first+1;
}

}

int count_mushrooms(int N) {
	int Q = 0;
	while (get_max_cnt(Q) < N) Q++;

	std::array<std::vector<int>, 2> knowns;
	knowns[0].reserve(N);
	knowns[1].reserve(N);

	knowns[0].push_back(0);
	std::vector<int> unknowns(N-1);
	std::iota(unknowns.begin(), unknowns.end(), 1);

	int ans = 0;
	while (!unknowns.empty()) {
		MOVE_TYPE t = get_max_cnt(int(knowns[0].size()), int(knowns[1].size()), Q).second;
		Q--;

		if (int(unknowns.size()) == 1) t = MOVE_TYPE::AxAxAxAx;

		switch (t) {
		case MOVE_TYPE::AxAx:
			{
				int z = knowns[0].size() >= knowns[1].size() ? 0 : 1;
				assert(knowns[z].size() >= 2);
				assert(unknowns.size() >= 2);
				int u = unknowns.back(); unknowns.pop_back();
				int v = unknowns.back(); unknowns.pop_back();
				int r = use_machine({u, knowns[z][0], v, knowns[z][1]});
				knowns[z ^ bool(r & 1)].push_back(u);
				knowns[z ^ bool(r & 2)].push_back(v);
			}
			break;
		case MOVE_TYPE::AxAxAxAx:
			{
				int z = knowns[0].size() >= knowns[1].size() ? 0 : 1;
				int s = std::min(int(knowns[z].size()), int(unknowns.size()));
				assert(s >= 1);

				std::vector<int> a; a.reserve(2*s);
				for (int i = 0; i < s; i++) {
					a.push_back(unknowns.back()); unknowns.pop_back();
					a.push_back(knowns[z][i]);
				}
				int u = a[0];
				int r = use_machine(a);
				knowns[z ^ bool(r & 1)].push_back(u);
				ans += z ? (r/2) : s-1-(r/2);
			}
			break;
		case MOVE_TYPE::xAx_xBx:
			{
				int s = std::min(
					2 * std::min(int(knowns[0].size()), int(knowns[1].size())),
					int(unknowns.size())
				);
				assert(s >= 1);
				int cur_val = 0;
				for (int z = 0; z < 2; z++) {
					std::vector<int> a; a.reserve(s + (s+1)/2);
					for (int i = 0; i < s; i++) {
						a.push_back(unknowns.back()); unknowns.pop_back();
						if (i % 2 == 0) {
							a.push_back(knowns[z][i/2]);
						}
					}
					int r = use_machine(a);
					if (z == 0) cur_val -= r;
					else cur_val += r;
				}
				assert((cur_val + s) % 2 == 0);
				ans += (cur_val + s) / 2;
			}
			break;
		default: assert(false);
		}
	}

	return ans + int(knowns[0].size());
}

// A few options:
// AxAx -> +2 known mushrooms
// AxAxAxAxAxAx -> +1 known, +(#A-1) counted
// xAxxAxxAxxAx - xBxxBxxBxxBx -> 2 queries, +2*min(#A, #B) counted
//
// xAxxAxxAxxAxxAxxAx
// xBxxBxxBxxBxxBxxBx
// subtract gives you the right counts
//
// Run k, we can get either 2/3k effective
// If we run k queries, we can get 2k known, 2/3 * 2k at a time
// k + 3/4 * n/k
// k ~ 4/3 n/k
# Verdict Execution time Memory Grader output
1 Correct 0 ms 256 KB Output is correct
2 Correct 0 ms 256 KB Output is correct
3 Correct 0 ms 256 KB Output is correct
4 Correct 1 ms 256 KB Output is correct
5 Correct 4 ms 640 KB Output is correct
6 Correct 165 ms 9976 KB Output is correct
7 Execution timed out 3069 ms 90580 KB Time limit exceeded
8 Halted 0 ms 0 KB -