Submission #715540

# Submission time Handle Problem Language Result Execution time Memory
715540 2023-03-27T07:40:20 Z jophyyjh Cup of Jamshid (IOI17_cup) C++14
100 / 100
1 ms 212 KB
/**
 * We only have 32 steps, so it's quite clear that we have to determine x,y bit
 * by bit. The process of finding this solution was through trial-and-error, so
 * I'll list some important observations and directly describe my sol.
 *  1. As the result of each query is |x-x'|^|y-y'|, when we've determined the
 *     hidden x' and we used a large (?!) enough y, y' can be immediately found
 *     since xor's inverse is itself.
 *  2. Write a value t in binary. |t - 2^d| and |t| differ only at the (d+1)-th
 *     least significant bit iff that bit of t is 1. (Well, at least this is
 *     true for t > 2^d. Take t=0 as a counter-example: our claim is false.)
 * 
 * 2. yields a good way to determine x' bit by bit. Here's the full solution:
 * (0) Let B = 5 * 10^8, pow be the unique power of 2 between B and 2B.
 * (1) Determine the sign of x', ask (pow,0): |y'| has at most 29 bits, while
 *      |B-x'| has its 30-th least sgn bit 1 iff x <= 0.
 * (2) We try to ask (~(-pow), whatever):   2. is best used when we know the
 *      num of bits in |x-x'|. WLOG let x' be positive. Each time, we can ask
 *      (-pow + 2^d, whatever) and compare it with the ans of (-pow, whatever).
 *      The clever trick here is that |x-x'| always has exactly 30 bits. In
 *      other words, (2) takes 30 steps.
 * 
 * Queries Needed:  31              (Bound not tight)
 * Implementation 1                 (Full solution, binary)
*/

#include <bits/stdc++.h>
#include "cup.h"

typedef std::vector<int>    vec;

const int B = 5e8, B2 = 1e9;
const int two_pow = 1 << 29;
const int MIN_DIGITS = 29;


vec find_cup() {
    int sign = ((ask_shahrasb(two_pow, 0) & two_pow) ? -1 : 1);
    int initial = ask_shahrasb(-sign * two_pow, B2);
    int x = 0;
    for (int _ = 0, d = 1; _ < MIN_DIGITS; _++, d <<= 1) {
        if ((ask_shahrasb(-sign * (two_pow - d), B2) ^ initial) == d)
            x |= d;
    }
    x *= sign;
    int y = B2 - (initial ^ std::abs(x + sign * two_pow));
    assert(std::abs(x) <= B && std::abs(y) <= B);
    return {x, y};
}
# Verdict Execution time Memory Grader output
1 Correct 1 ms 212 KB Output is correct