Submission #1252184

#TimeUsernameProblemLanguageResultExecution timeMemory
1252184kuroba선물 (IOI25_souvenirs)C++20
100 / 100
12 ms420 KiB
#include "souvenirs.h"

#include <iostream>
using namespace std;

// Compile with:
// g++ -std=gnu++20 -O2 -o souvenir souvenirs.h souvenirs.cpp
// Can call:
// std::pair<std::vector<int>, long long> transaction(long long M)
long long price[101];
long long bought[101];
bool debug = false;
void recurse(int N, long long guess) {
    pair<vector<int>, long long> ret = transaction(guess);
    vector<int>& items = ret.first;
    long long remainder = ret.second;
    for (int i = 0; i < items.size(); i++) {
        bought[items[i]]++;
    }

    if (debug) {
        cout << "Transaction: " << guess << " returns (";
        for (int i = 0; i < items.size(); i++) {
            cout << items[i] << " ";
        }
        cout << ") and remainder " << remainder << endl;
    }
    if (items.size() == 1) {
        // only hit one item
        // we know it's exact value.
        long long s = guess - remainder;
        price[items[0]] = s;
        if (debug) {
            cout << "Deduced price[" << items[0] << "] = " << s << endl;
        }
        if (items[0] < N-1) {
            // if there's more items to the right,
            // we should recurse further
            recurse(N, s-1);
        }
    }
    else {
        // hit multiple items
        // Guess the average of them (this is guaranteed to be safe).

        // While we don't know the price of all of our items, make "safe" guesses,
        //
        while (true) {
            int known_items = 0;
            int last_unknown_idx = 0;
            long long s = guess - remainder;
            for (int i = 0; i < items.size(); i++) {
                if (price[items[i]] != 0) {
                    known_items += 1;
                    s -= price[items[i]];
                }
                else {
                    last_unknown_idx = i;
                }
            }
            if (known_items == items.size()-1) {
                price[items[last_unknown_idx]] = s;
                if (debug) {
                    cout << "Deduced price[" << items[last_unknown_idx] << "] = " << s << endl;
                }
                known_items += 1;
            }
            if (known_items == items.size()) {
                break;
            }
            long long unknown_items = items.size() - known_items;

            if (debug) {
                cout << "known_items = " << known_items << ", unknown_items = " << unknown_items << ", s = " << s << endl;
                cout << "state transaction: " << guess << " returns (";
                for (int i = 0; i < items.size(); i++) {
                    cout << items[i] << " ";
                }
                cout << ") and remainder " << remainder << endl;
                for (int i = 0; i < N; i++) {
                    cout << "i = " << i << ", p = " << price[i] << ", b = " << bought[i] << endl;
                }
                // for (int i = 0; i < items.size(); i++) {
                //     cout << "item: " << items[i] << " " << price[items[i]] << endl;
                // }
                // cout << "Starting new recursion with " << s / unknown_items << endl;
            }
            recurse(N, s / unknown_items);
        }
    }
    // Find the next smallest number that we don't know.
    for (int i = N-1; i > items[0]; i--) {
        if (price[i] == 0 && price[i-1] != 0) {
            recurse(N, price[i-1] - 1);
        }
    }
}

void buy_souvenirs(int N, long long P0) {
    long long x = P0;
    for (int i = 0; i < N; i++) {
        price[i] = 0;
        bought[i] = 0;
    }
    price[0] = P0;
    for (int i = 1; i < N; i++) {
        if (price[i] == 0) {
            if (debug) {
                cout << "Top level call for " << i << endl;
            }
            recurse(N, price[i-1] - 1);       
        }
        if (price[i] == 0) {
            cout << "Failed to deduce " << i << endl;
            return;
        }
    }
    
    for (int i = 0; i < N; i++) {
        while (bought[i] < i){
            if (price[i] != 0) {
                transaction(price[i]);
                bought[i]++;
            }
            else {
                cout << "Did not deduce price of " << i << endl;
                break;
            }
        }
    }
    if (debug) {
        cout << "Final answer: " << endl;
        for (int i = 0; i < N; i++) {
            cout << i << ": " << price[i] << ", " << bought[i] << endl;
        }
    }
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...