| # | Time | Username | Problem | Language | Result | Execution time | Memory | 
|---|---|---|---|---|---|---|---|
| 337016 | aanastasov | Counting Mushrooms (IOI20_mushrooms) | C++17 | 1 ms | 620 KiB | 
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 "mushrooms.h"
#include <algorithm>
#include <array>
#include <cassert>
#include <iostream>
#include <map>
#include <vector>
template<typename T> void show(std::vector<T> v) {
    std::cout << "{";
    for (int i = 0; i < v.size(); ++i) {
        if (i > 0) std::cout << ", ";
        std::cout << v[i];
    }
    std::cout << "}";
}
class Knowledge {
public:
    std::array<int, 2> count{0, 0};
    std::array<std::vector<int>, 2> indicesOfKnown;
    void merge(Knowledge &other) {
        for (int color = 0; color < count.size(); ++color) {
            count[color] += other.count[color];
            for (auto index : other.indicesOfKnown[color])
                indicesOfKnown[color].push_back(index);
        }
    }
};
class AbstractEngine {
public:
    virtual bool canRun(Knowledge& current) = 0;
    virtual bool enoughUnknowns(std::vector<int>& indicesOfUnknown) = 0;
    virtual int maxToTake(Knowledge& current) = 0;
    virtual Knowledge run(Knowledge& current, std::vector<int>& indicesOfUnknown) = 0;
};
class CountEngine : public AbstractEngine {
public:
    CountEngine(int varsCount) {
        this->varsCount = varsCount;
    }
    virtual bool canRun(Knowledge& current) {
        return current.indicesOfKnown[0].size() >= varsCount 
                || current.indicesOfKnown[1].size() >= varsCount;
    }
    virtual bool enoughUnknowns(std::vector<int>& indicesOfUnknown) {
        return indicesOfUnknown.size() >= this->varsCount;
    }
    virtual int maxToTake(Knowledge& current) {
        return std::max(current.indicesOfKnown[0].size(), current.indicesOfKnown[1].size());
    }
    virtual Knowledge run(Knowledge& current, std::vector<int>& indicesOfUnknown) {
        const int color = (current.indicesOfKnown[0].size() > current.indicesOfKnown[1].size())
            ? 0 : 1;
        const int querySize = std::min(indicesOfUnknown.size(),
                current.indicesOfKnown[color].size());
        auto arr = std::vector<int>(querySize * 2);
        for (int index = 0; index < querySize; ++index) {
            arr[index * 2] = current.indicesOfKnown[color][index];
            arr[index * 2 + 1] = indicesOfUnknown[index];
        }
        int count = use_machine(arr);
        Knowledge response;
        if (color == 1) {
            response.count[0] += count / 2;
            response.count[1] += (int)(querySize - 1) - response.count[0];
        } else {
            response.count[1] += count / 2;
            response.count[0] += (int)(querySize - 1) - response.count[1];
        }
        int lastValue = (color != 0 ? 1 : 0) ^ (count % 2 != 0 ? 1 : 0);
        response.indicesOfKnown[lastValue].push_back(indicesOfUnknown.back());
        response.count[lastValue]++;
        return response;
    }
private:
    int varsCount;
};
class FullEngine : public AbstractEngine {
public:
    FullEngine(int varsCount, int queriesCount, std::vector<std::vector<int>> queries) {
        this->varsCount = varsCount;
        this->queriesCount = queriesCount;
        this->queries = queries;
        determineReverseMap();
    }
    virtual bool canRun(Knowledge& current) {
        for (int color = 0; color < current.count.size(); ++color)
            if (current.indicesOfKnown[color].size() >= varsCount) {
                return true;
            }
        return false;
    }
    virtual bool enoughUnknowns(std::vector<int>& indicesOfUnknown) {
        return true;
    }
    virtual int maxToTake(Knowledge ¤t) {
        return varsCount;
    }
    virtual Knowledge run(Knowledge& current, std::vector<int>& indicesOfUnknown) {
        assert(canRun(current));
        assert(indicesOfUnknown.size() == varsCount);
        auto queryAnswers = std::vector<int>();
        const int color = (current.indicesOfKnown[0].size() >= varsCount) ? 0 : 1;
        auto& indicesOfKnown = current.indicesOfKnown[color];
        for (auto query : queries) {
            auto arr = std::vector<int>(query.size() * 2);
            for (int index = 0; index < query.size(); ++index) {
                arr[index * 2] = indicesOfKnown[index];
                arr[index * 2 + 1] = indicesOfUnknown[query[index]];
            }
            queryAnswers.push_back(use_machine(arr));
        }
        assert(reverseMap[color].count(queryAnswers));
        auto varsValues = reverseMap[color][queryAnswers];
        assert(varsValues.size() == varsCount);
        Knowledge response;
        for (int index = 0; index < varsValues.size(); ++index) {
            response.indicesOfKnown[varsValues[index]].push_back(indicesOfUnknown[index]);
            response.count[varsValues[index]]++;
        }
        return response;
    }
private:
    void determineReverseMap() {
        auto countDiffPairs = [&](std::vector<int> arr) {
            int res = 0;
            for (int i = 0; i < arr.size(); ++i) {
                assert(arr[i] == 0 || arr[i] == 1);
                if (i > 0 && arr[i] != arr[i - 1]) ++res;
            }
            return res;
        };
        for (int color = 0; color < 2; ++color) {
            for (int varsSet = 0; varsSet < (1 << varsCount); ++varsSet) {
                std::vector<int> varsValues;
                for (int index = 0; index < varsCount; ++index)
                    varsValues.push_back((varsSet >> index) & 1);
                std::vector<int> queryAnswers(queriesCount);
                for (int query = 0; query < queriesCount; ++query) {
                    std::vector<int> arr(queries[query].size() * 2);
                    for (int index = 0; index < queries[query].size(); ++index) {
                        arr[index * 2] = color;
                        arr[index * 2 + 1] = varsValues[queries[query][index]];
                    }
                    queryAnswers[query] = countDiffPairs(arr);
                }
                assert(reverseMap[color].count(queryAnswers) == 0);
                reverseMap[color][queryAnswers] = varsValues;
            }
        }
    }
    int varsCount;
    int queriesCount;
    std::vector<std::vector<int>> queries;
    std::array<std::map<std::vector<int>, std::vector<int>>, 2> reverseMap;
};
std::vector<int> take(std::vector<int>& arr, int count) {
    if (count >= arr.size())
        count = arr.size();
    assert(count <= arr.size());
    std::vector<int> res;
    while (count > 0) {
        res.push_back(arr.back());
        arr.pop_back();
        count--;
    }
    return res;
}
int count_mushrooms(int n) {
    Knowledge currentKnowledge;
    currentKnowledge.indicesOfKnown[0].push_back(0);
    currentKnowledge.count[0] = 1;
    FullEngine oneBitEfficiency(1, 1, {{0}});
    FullEngine twoBitEfficiency(2, 1, {{0, 1}});
    FullEngine twoAndAThirdBitEfficiency(7, 3, {{0, 1, 4}, {0, 2, 5}, {1, 2, 3, 6}});
    CountEngine countEfficiency(95);
    auto engines = std::vector<AbstractEngine *>{&countEfficiency, &twoAndAThirdBitEfficiency,
        &twoBitEfficiency, &oneBitEfficiency};
    auto indicesOfUnknown = std::vector<int>(n - 1);
    for (int index = 0; index < indicesOfUnknown.size(); ++index)
        indicesOfUnknown[index] = index + 1;
    std::reverse(indicesOfUnknown.begin(), indicesOfUnknown.end());
    while (!indicesOfUnknown.empty()) {
        auto curIndicesOfUnknown = std::vector<int>();
        Knowledge derivedKnowledge;
        for (auto* engine : engines) {
            if (!engine->canRun(currentKnowledge)) continue;
            const int maxToTake = engine->maxToTake(currentKnowledge);
            auto indicesOfUnknownToTake = take(indicesOfUnknown, maxToTake);
            derivedKnowledge = engine->run(currentKnowledge, indicesOfUnknownToTake);
            break;
        }
        currentKnowledge.merge(derivedKnowledge);
    }
    return currentKnowledge.count[0];
}
Compilation message (stderr)
| # | Verdict | Execution time | Memory | Grader output | 
|---|---|---|---|---|
| Fetching results... | ||||
