Submission #1026699

# Submission time Handle Problem Language Result Execution time Memory
1026699 2024-07-18T09:23:21 Z 우민규(#10946) COVID tests (CEOI24_covid) C++17
0 / 100
74 ms 344 KB
#include <bits/stdc++.h>
using namespace std;

int n, t;
double p;
vector<double> exp_query(1001);
vector<int> exp_chunk(1001);

vector<double> exp_exist_query(1001), exp_idk_query(1001);
vector<int> exp_exist_chunk(1001), exp_idk_chunk(1001);
vector<bool> did_check_all(1001);
string ans;
int qcnt = 0;

bool ask(string& s) {
  qcnt += 1;
  for (int i = 0; i < ans.size(); ++i)
    if (s[i] == '1' && ans[i] == '1') return true;
  return false;
  // cout << "Q " << s << endl;
  // char c;
  // cin >> c;
  // return c == 'P';
}

string ill;
mt19937_64 gen(6974);

vector<int> to_ask_next;
void solve(vector<int> candidate, bool certain_exists = false) {
  if (candidate.size() == 1) {
    // if n > 1, this must be from a recursive solve call
    // thus, there must be a patient in [l, r), which means that l is ill
    string cur(n, '0');
    cur[candidate[0]] = '1';
    if (certain_exists || ask(cur)) ill[candidate[0]] = '1';
    return;
  }
  if (did_check_all[candidate.size()] && !certain_exists) {
    string cur(n, '0');
    for (auto e : candidate) cur[e] = '1';
    if (ask(cur)) solve(candidate, true);
    return;
  }
  int chunk = certain_exists ? exp_exist_chunk[candidate.size()]
                             : exp_idk_chunk[candidate.size()];
  string cur(n, '0');
  vector<int> next_candidate;
  for (int j = 0; j < chunk; ++j) {
    cur[candidate.back()] = '1';
    next_candidate.push_back(candidate.back());
    candidate.pop_back();
  }
  if (!certain_exists)
    to_ask_next.insert(to_ask_next.end(), candidate.begin(), candidate.end());
  if (ask(cur)) {
    solve(next_candidate, true);
    if (certain_exists) solve(candidate, false);
  } else {
    if (certain_exists) solve(candidate, certain_exists);
  }
}

void upd(double& a, int& b, double c, int d) {
  if (a > c) {
    a = c;
    b = d;
  }
}

void solve() {
  // ill = string(n, '0');
  // vector<int> candidates(n);
  // iota(candidates.begin(), candidates.end(), 0);
  // solve(candidates);
  // cout << "A " << ill << endl;
  // char c;
  // cin >> c;
  // if (c == 'C') return;
  // // WA
  // exit(EXIT_SUCCESS);
  mt19937_64 gen(6974);
  double reqs[] = {15.1, 51.1, 94.9, 191.5, 246.3, 366.2, 490.3, 639.1, 731.4};
  int i = 0;
  for (auto p : {0.001, 0.005256, 0.011546, 0.028545, 0.039856, 0.068648,
                 0.104571, 0.158765, 0.2}) {
    auto req = reqs[i++];
    exp_exist_query[1] = 0;
    exp_idk_query[1] = 1;
    exp_query[1] = 0, exp_chunk[1] = 1;
    for (int i = 2; i < 1001; ++i) {
      exp_exist_query[i] = 999999;
      exp_idk_query[i] = 999999;
      for (int k = 1; k < i; ++k) {
        // exp_exist
        double does_exist_prob = (1 - pow(1 - p, k)) / (1 - pow(1 - p, i));
        upd(exp_exist_query[i], exp_exist_chunk[i],
            1 + does_exist_prob * (exp_exist_query[k] + exp_idk_query[i - k]) +
                (1 - does_exist_prob) * exp_exist_query[i - k],
            k);

        // exp_idk
        does_exist_prob = 1 - pow(1 - p, k);
        upd(exp_idk_query[i], exp_idk_chunk[i],
            1 + does_exist_prob * exp_exist_query[k] + exp_idk_query[i - k], k);

        // pick k randomly -> discard upon zero
        // if (pow(1 - p, -k) <= 10)
        //   exp_idk_query[i] =
        //       min(exp_idk_query[i], pow(1 - p, -k) + exp_idk_query[i -
        // k]);
      }
      if (exp_idk_query[i] > 1 + (1 - pow(1 - p, i)) * exp_exist_query[i]) {
        exp_idk_query[i] = 1 + (1 - pow(1 - p, i)) * exp_exist_query[i];
        did_check_all[i] = true;
      } else {
        did_check_all[i] = false;
      }
    }
    cout << fixed << setprecision(3) << p << ":\t" << req << "\t"
         << exp_idk_query[n] << "\t" << endl;
    //  << req / (req + 4 * max(exp_idk_query[n] - req, 0.)) * 90 << endl;

    //   exp_query[1] = 1, exp_chunk[1] = 1;
    //   for (int i = 2; i <= n; ++i) {
    //     double expected = 999999;
    //     int expected_chunk = -1;
    //     for (int k = 1; k < i; ++k) {
    //       int chunks = (i + (k - 1)) / k;
    //       double prob = 1 - pow(1 - p, k);
    //       double cur_exp =
    //           (chunks * prob / (1 - pow(1 - p, i))) * exp_query[k] + chunks;
    //       if (cur_exp < expected) {
    //         expected_chunk = k;
    //         expected = cur_exp;
    //       }
    //     }
    //     exp_query[i] = expected;
    //     exp_chunk[i] = expected_chunk;
    //   }

    uniform_real_distribution<double> distrib(0, 1);
    int tot_q = 0;
    const int tests = 100;
    for (int t = 0; t < tests; ++t) {
      ans = string(n, '0');
      qcnt = 0;
      for (int i = 0; i < ans.size(); ++i)
        if (distrib(gen) < p) ans[i] = '1';
      ill = string(n, '0');

      vector<int> arr(n);
      iota(arr.begin(), arr.end(), 0);
      while (!arr.empty()) {
        // shuffle arr
        for (int i = arr.size() - 1; i > 0; --i)
          swap(arr[i], arr[gen() % (i + 1)]);
        solve(arr);
        arr.clear();
        arr.swap(to_ask_next);
      }
      if (ill != ans) {
        cout << "WA\n";
      }
      tot_q += qcnt;
    }
    double avg_q = (double)tot_q / tests;
    cout << "res:\t" << req << "\t" << avg_q << "\t"
         << req / (req + 4 * max(avg_q - req, 0.)) * 90 << endl;
  }
}

int main() {
  cin.tie(0)->sync_with_stdio(0);
  cin >> n >> p >> t;
  if (t == 1) {
    exp_exist_chunk.assign(1001, 1);
    exp_idk_chunk.assign(1001, 1);
  } else {
    exp_exist_query[1] = 0;
    exp_idk_query[1] = 1;
    exp_query[1] = 0, exp_chunk[1] = 1;
    for (int i = 2; i < 1001; ++i) {
      exp_exist_query[i] = 999999;
      exp_idk_query[i] = 999999;
      for (int k = 1; k < i; ++k) {
        // exp_exist
        double does_exist_prob = (1 - pow(1 - p, k)) / (1 - pow(1 - p, i));
        upd(exp_exist_query[i], exp_exist_chunk[i],
            1 + does_exist_prob * (exp_exist_query[k] + exp_idk_query[i - k]) +
                (1 - does_exist_prob) * exp_exist_query[i - k],
            k);

        // exp_idk
        does_exist_prob = 1 - pow(1 - p, k);
        upd(exp_idk_query[i], exp_idk_chunk[i],
            1 + does_exist_prob * exp_exist_query[k] + exp_idk_query[i - k], k);
      }
      if (exp_idk_query[i] > 1 + (1 - pow(1 - p, i)) * exp_exist_query[i]) {
        exp_idk_query[i] = 1 + (1 - pow(1 - p, i)) * exp_exist_query[i];
        did_check_all[i] = true;
      } else {
        did_check_all[i] = false;
      }
    }
  }
  for (int i = 0; i < t; ++i) {
    solve();
  }
  return 0;
}

Compilation message

Main.cpp: In function 'bool ask(std::string&)':
Main.cpp:17:21: warning: comparison of integer expressions of different signedness: 'int' and 'std::__cxx11::basic_string<char>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   17 |   for (int i = 0; i < ans.size(); ++i)
      |                   ~~^~~~~~~~~~~~
Main.cpp: In function 'void solve()':
Main.cpp:148:25: warning: comparison of integer expressions of different signedness: 'int' and 'std::__cxx11::basic_string<char>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  148 |       for (int i = 0; i < ans.size(); ++i)
      |                       ~~^~~~~~~~~~~~
# Verdict Execution time Memory Grader output
1 Runtime error 74 ms 344 KB Execution killed with signal 13
2 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Runtime error 30 ms 344 KB Execution killed with signal 13
2 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Runtime error 54 ms 344 KB Execution killed with signal 13
2 Halted 0 ms 0 KB -