Submission #1294447

#TimeUsernameProblemLanguageResultExecution timeMemory
1294447m_bezrutchkaCounting Mushrooms (IOI20_mushrooms)C++20
88.63 / 100
6 ms448 KiB
// 92 points, q = 245 #include "mushrooms.h" #include <bits/stdc++.h> using namespace std; // alguma informacao que ainda nao estamos usando? // - de que nossas queries do passo 2 tem todos os elementos conhecidos iguais // - entao, paridade determina o valor do primeiro desconhecido // - isso quer dizer que cada query do passo 2 contribui em 1 // para os sets do passo 1 // entao vamos usar: // - passo 1: k queries para encontrar k iguais, como antes // - passo 2: vamos sempre usando o maior set e atualizando os sets // total de caras novos descobertos a cada passo vai aumentando // k, k+1, k+1, k+2, k+2, ..., s, s // se no final o tamanho do set é s, eu tenho // // total de posicoes contadas: // (2k - 1) + 2k + 2(k+1) + 2*(k+2) + ... + 2s // // quero // (2k - 1) + 2k + 2(k+1) + 2*(k+2) + ... + 2s >= n // 1 + 2*((k-1) + k + k+1 + ... + s) >= n // 2 * soma(k-1, s) >= n // s * (s + 1) - (k - 2) * (k - 1) >= n // arredonda pra // s^2 - (k - 1)^2 >= n // // (s - k) * (s + k) >= n // // numero de queries: k + 2 * (s - k) - 1 = 2s + k - 1 // queremos 2s + k - 1 <= 226 // s precisa ser > 100 // vamos chutar s = 105: // posso fazer k = 33 // fica 210 + 33 - 1 = 245 queries // // parece que nao da pra melhorar muito de 245 // // int count_mushrooms(int n) { if (n == 1) return 1; vector<int> pos_A; vector<int> pos_B; pos_A.push_back(0); if (use_machine({0, 1}) == 0) pos_A.push_back(1); else pos_B.push_back(1); if (n == 2) return ((int) pos_A.size()); if (use_machine({0, 2}) == 0) pos_A.push_back(2); else pos_B.push_back(2); int k = 36; // passo 1 for (int i = 3; i < 2 * k - 1; i += 2) { if (i == n) return ((int) pos_A.size()); if (i == n - 1) { return ((int) pos_A.size()) + (1 - use_machine({0, i})); } if ((int) pos_A.size() >= 2) { int ret = use_machine({i, pos_A[0], i+1, pos_A[1]}); if (ret == 0) { pos_A.push_back(i); pos_A.push_back(i+1); } else if (ret == 1) { pos_B.push_back(i); pos_A.push_back(i+1); } else if (ret == 2) { pos_A.push_back(i); pos_B.push_back(i+1); } else { pos_B.push_back(i); pos_B.push_back(i+1); } } else { int ret = use_machine({i, pos_B[0], i+1, pos_B[1]}); if (ret == 3) { pos_A.push_back(i); pos_A.push_back(i+1); } else if (ret == 2) { pos_B.push_back(i); pos_A.push_back(i+1); } else if (ret == 1) { pos_A.push_back(i); pos_B.push_back(i+1); } else { pos_B.push_back(i); pos_B.push_back(i+1); } } } int step = pos_A.size(); bool using_b = false; if (pos_A.size() < pos_B.size()) { using_b = true; step = pos_B.size(); } // cout << "pos_A: "; // for (int x: pos_A) { // cout << x << " "; // } // cout << endl; // cout << "pos_B: "; // for (int x: pos_B) { // cout << x << " "; // } // cout << endl; // cout << "using_b = " << using_b << endl; // cout << "step = " << step << endl; int ans = pos_A.size(); int ini = 2 * k - 1; while (ini < n) { // ini x0 ini+1 x1 ini+2 x2 ... ini+step-1 xstep-1 // alternadamente vector<int> aux; int last = min(n - 1, ini + step - 1); int cur_sz = last - ini + 1; for (int j = 0; j < cur_sz; j++) { aux.push_back({ini + j}); int pos_to_use = using_b ? pos_B[j] : pos_A[j]; aux.push_back(pos_to_use); } // cout << "will make query "; // for (int x: aux) { // cout << x << " "; // } // cout << endl; int ret = use_machine(aux); // cout << "got " << ret << endl; if (using_b) { ans += (ret + 1) / 2; if (ret % 2 == 0) { pos_B.push_back(ini); } else { pos_A.push_back(ini); } } else { ans += cur_sz - (ret + 1) / 2; if (ret % 2 == 0) { pos_A.push_back(ini); } else { pos_B.push_back(ini); } } ini += cur_sz; // cout << "now ans = " << ans << endl; // cout << "now ini = " << ini << endl; step = pos_A.size(); using_b = false; if (pos_A.size() < pos_B.size()) { using_b = true; step = pos_B.size(); } } return ans; }
#Verdict Execution timeMemoryGrader output
Fetching results...