Submission #1273678

#TimeUsernameProblemLanguageResultExecution timeMemory
1273678lucas110550Souvenirs (IOI25_souvenirs)C++20
100 / 100
13 ms400 KiB
#include "souvenirs.h" #include <bits/stdc++.h> using namespace std; const int MAXN = 105; // N ≤ 100 struct Equation { bitset<MAXN> mask; // unknown indices (0‑based for types 1..N‑1) long long rhs; // sum of their prices }; int N_; long long P0_; vector<long long> price; // -1 while unknown, size N (0..N‑1) vector<int> bought; // how many copies we already have vector<Equation> eqs; // linear equations for unknowns /*---------------------------------------------------------------*/ static long long min_unknown_higher_price(int idx) // smallest known price among types < idx, -1 if none { long long best = -1; for (int i = 0; i < idx; ++i) { if (price[i] != -1) { if (best == -1 || price[i] < best) best = price[i]; } } return best; // -1 means “none known” } /* try to solve all equations that became singletons */ static void reduce_system() { bool changed = true; while (changed) { changed = false; for (size_t e = 0; e < eqs.size(); ++e) { if (eqs[e].mask.none()) continue; if (eqs[e].mask.count() == 1) { int idx = (int)eqs[e].mask._Find_first(); // index 0..N-2 (type = idx+1) long long val = eqs[e].rhs; if (price[idx] == -1) { price[idx] = val; } // substitute into all equations for (size_t k = 0; k < eqs.size(); ++k) { if (eqs[k].mask[idx]) { eqs[k].rhs -= val; eqs[k].mask.reset(idx); } } // also subtract from bought counts – // the copy obtained in the transaction that gave this equation // has already been counted when the transaction was processed. eqs[e].mask.reset(); // make it empty changed = true; } } } } /*---------------------------------------------------------------*/ void buy_souvenirs(int N, long long P0) { N_ = N; P0_ = P0; price.assign(N, -1); // price[0] is known (P0), others -1 price[0] = P0; bought.assign(N, 0); // counts for all types, we never buy type 0 // ---------- discovery phase ---------- // start with a safe upper bound for the cheapest unknown price long long UB_initial = P0 - (N - 1); // Lemma 1 // we will repeat until all prices (1..N-1) are known while (true) { bool all_known = true; for (int i = 1; i < N; ++i) if (price[i] == -1) { all_known = false; break; } if (all_known) break; // 1) compute an upper bound for the smallest unknown price long long bound1 = (long long)4e18; // INF // find the smallest known price among indices smaller than the current smallest unknown int smallest_unknown = -1; for (int i = N - 1; i >= 1; --i) if (price[i] == -1) { smallest_unknown = i; break; } long long higher = min_unknown_higher_price(smallest_unknown); if (higher != -1) bound1 = higher - 1; // must be < any more expensive known price long long bound2 = (long long)4e18; for (auto &eq : eqs) { if (eq.mask.none()) continue; long long cnt = (long long)eq.mask.count(); long long cand = eq.rhs / cnt; // floor if (cand < bound2) bound2 = cand; } long long UB = min(bound1, bound2); if (UB == (long long)4e18) UB = UB_initial; // fallback, should not happen // 2) perform the transaction auto resp = transaction(UB); const vector<int> &L = resp.first; long long R = resp.second; long long sum = UB - R; // Σ P[t] over all bought types // 3) update data structures bitset<MAXN> curMask; for (int t : L) { ++bought[t]; // we obtained one copy of this type int idx = t; // type number = index (0..N-1) if (idx == 0) continue; // we never get type 0 because M < P0 if (price[idx] != -1) { sum -= price[idx]; // known contribution } else { curMask.set(idx); } } if (curMask.any()) { Equation ne; ne.mask = curMask; ne.rhs = sum; eqs.push_back(ne); } // 4) try to solve singletons that appeared reduce_system(); } // ---------- finishing purchases ---------- for (int i = 1; i < N; ++i) { int need = i - bought[i]; for (int k = 0; k < need; ++k) { transaction(price[i]); // buys exactly one copy of type i } } }
#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...