Problem: cf1088_d
Difficulty: medium
Categories: bit, greedy
Time limit: 1000 ms, memory limit: 256 MB

This is an interactive problem!

Ehab plays a game with Laggy. Ehab has 2 hidden integers $(a,b)$. Laggy can ask a pair of integers $(c,d)$ and Ehab will reply with:

* 1 if $a \oplus c>b \oplus d$.
* 0 if $a \oplus c=b \oplus d$.
* -1 if $a \oplus c<b \oplus d$.

Operation $a \oplus b$ is the bitwise-xor operation of two numbers $a$ and $b$.

Laggy should guess $(a,b)$ with at most 62 questions. You'll play this game. You're Laggy and the interactor is Ehab.

It's guaranteed that $0 \le a,b<2^{30}$.

Input

See the interaction section.

Output

To print the answer, print "! a b" (without quotes). Don't forget to flush the output after printing the answer.

Interaction

To ask a question, print "? c d" (without quotes). Both $c$ and $d$ must be non-negative integers less than $2^{30}$. Don't forget to flush the output after printing any question.

After each question, you should read the answer as mentioned in the legend. If the interactor replies with -2, that means you asked more than 62 queries and your program should terminate.

To flush the output, you can use:-

* fflush(stdout) in C++.
* System.out.flush() in Java.
* stdout.flush() in Python.
* flush(output) in Pascal.
* See the documentation for other languages.

Example

Input

```
1  
-1  
0
```

Output

```? 2 1? 1 2? 2 0! 3 1
```

Note

In the sample:

The hidden numbers are $a=3$ and $b=1$.

In the first query: $3 \oplus 2 = 1$ and $1 \oplus 1 = 0$, so the answer is 1.

In the second query: $3 \oplus 1 = 2$ and $1 \oplus 2 = 3$, so the answer is -1.

In the third query: $3 \oplus 2 = 1$ and $1 \oplus 0 = 1$, so the answer is 0.

Then, we printed the answer.

Non-adaptive interactor (C++):
#include "testlib.h"
#include <bits/stdc++.h>
using namespace std;

static long long queries = 0;
static long long query_limit = 0;

static void log_metrics() {
    try {
        tout << "queries=" << queries << "\n";
        tout << "query_limit=" << query_limit << "\n";
        tout.flush();
    } catch (...) {
        
    }
}

static void finish(TResult verdict, const string& msg) {
    log_metrics();
    quitf(verdict, "%s", msg.c_str());
}

static bool parseLongLongStrict(const string& s, long long& out) {
    if (s.empty()) return false;
    int i = 0;
    bool neg = false;
    if (s[i] == '+' || s[i] == '-') {
        neg = (s[i] == '-');
        i++;
        if (i == (int)s.size()) return false;
    }
    long long val = 0;
    for (; i < (int)s.size(); i++) {
        char ch = s[i];
        if (ch < '0' || ch > '9') return false;
        int d = ch - '0';
        if (val > (LLONG_MAX - d) / 10) return false;
        val = val * 10 + d;
    }
    out = neg ? -val : val;
    return true;
}

int main(int argc, char** argv) {
    registerInteraction(argc, argv);
    atexit(log_metrics);

    const long long LIM = 1LL << 30;

    long long a = inf.readLong();
    long long b = inf.readLong();
    if (!(0 <= a && a < LIM && 0 <= b && b < LIM)) {
        query_limit = 62;
        log_metrics();
        finish(_pe, "hidden input (a,b) out of bounds");
    }

    query_limit = 62;
    log_metrics(); 

    const long long hard_cap = max(200000LL, 10LL * query_limit);

    try {
        string line;
        while (true) {
            if (!std::getline(cin, line)) {
                finish(_wa, "EOF before answer");
            }

            
            bool allSpace = true;
            for (char ch : line) {
                if (!isspace((unsigned char)ch)) {
                    allSpace = false;
                    break;
                }
            }
            if (allSpace) continue;

            stringstream ss(line);
            string cmd;
            ss >> cmd;
            if (cmd != "?" && cmd != "!") {
                finish(_pe, "invalid command (expected '?' or '!')");
            }

            vector<string> toks;
            string tok;
            while (ss >> tok) toks.push_back(tok);

            if (cmd == "?") {
                if (toks.size() != 2) finish(_pe, "query must be: ? c d");
                long long c, d;
                if (!parseLongLongStrict(toks[0], c) || !parseLongLongStrict(toks[1], d)) {
                    finish(_pe, "non-integer in query");
                }
                if (!(0 <= c && c < LIM && 0 <= d && d < LIM)) {
                    finish(_pe, "query numbers out of bounds");
                }

                queries++;
                if (queries > hard_cap) finish(_pe, "too many queries (hard cap exceeded)");

                int reply = -2;
                if (queries <= query_limit) {
                    long long x = (a ^ c);
                    long long y = (b ^ d);
                    if (x > y) reply = 1;
                    else if (x < y) reply = -1;
                    else reply = 0;
                }

                cout << reply << endl; 
            } else { 
                if (toks.size() != 2) finish(_pe, "answer must be: ! a b");
                long long ga, gb;
                if (!parseLongLongStrict(toks[0], ga) || !parseLongLongStrict(toks[1], gb)) {
                    finish(_pe, "non-integer in answer");
                }
                if (!(0 <= ga && ga < LIM && 0 <= gb && gb < LIM)) {
                    finish(_wa, "answer out of bounds");
                }
                if (ga == a && gb == b) {
                    finish(_ok, "correct");
                } else {
                    finish(_wa, "wrong answer");
                }
            }
        }
    } catch (const exception& e) {
        finish(_pe, string("exception: ") + e.what());
    } catch (...) {
        finish(_pe, "unknown exception");
    }
    return 0;
}


Adaptive interactor (C++):
#include "testlib.h"
#include <bits/stdc++.h>
using namespace std;

static long long queries = 0;
static long long query_limit = 0;

static void log_metrics() {
    try {
        tout << "queries=" << queries << "\n";
        tout << "query_limit=" << query_limit << "\n";
        tout.flush();
    } catch (...) {
        
    }
}

static void finish(TResult verdict, const string& msg) {
    log_metrics();
    quitf(verdict, "%s", msg.c_str());
}

static uint64_t splitmix64(uint64_t& x) {
    x += 0x9e3779b97f4a7c15ULL;
    uint64_t z = x;
    z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9ULL;
    z = (z ^ (z >> 27)) * 0x94d049bb133111ebULL;
    return z ^ (z >> 31);
}

int main(int argc, char** argv) {
    registerInteraction(argc, argv);
    atexit(log_metrics);

    bool adaptive_mode = false;
    int bits = 30;

    long long first = 0;
    try {
        first = inf.readLong();
    } catch (...) {
        finish(_pe, "bad hidden input");
    }

    uint32_t hidden_a = 0, hidden_b = 0;
    bool chosen = false;

    if (inf.seekEof()) {
        adaptive_mode = true;
        bits = (int)first;
        if (bits < 1 || bits > 30) finish(_pe, "bits out of range in hidden input");
    } else {
        adaptive_mode = false;
        long long second = 0;
        try {
            second = inf.readLong();
            inf.readEof();
        } catch (...) {
            finish(_pe, "bad hidden input format");
        }
        if (first < 0 || first >= (1LL << 30) || second < 0 || second >= (1LL << 30)) {
            finish(_pe, "a/b out of allowed range in hidden input");
        }
        hidden_a = (uint32_t)first;
        hidden_b = (uint32_t)second;
        chosen = true;
        bits = 30;
    }

    query_limit = 62;
    log_metrics(); 

    const long long hard_cap = max(200000LL, 10LL * query_limit);
    const uint32_t MASK = (bits == 32 ? 0xFFFFFFFFu : ((bits == 32) ? 0xFFFFFFFFu : ((1u << bits) - 1u)));
    const long long LIM30 = (1LL << 30);

    auto choose_hidden_from_first_query = [&](long long c, long long d) {
        uint64_t seed = (uint64_t)((uint32_t)c) << 32;
        seed ^= (uint64_t)(uint32_t)d;
        seed ^= (uint64_t)bits * 0x9e3779b97f4a7c15ULL;
        uint64_t r1 = splitmix64(seed);
        uint64_t r2 = splitmix64(seed);
        hidden_a = (uint32_t)(r1 & MASK);
        hidden_b = (uint32_t)(r2 & MASK);
        if (hidden_a == hidden_b) {
            hidden_b ^= 1u;
            hidden_b &= MASK;
        }
        chosen = true;
    };

    while (true) {
        string cmd;
        if (!(cin >> cmd)) finish(_pe, "unexpected EOF from contestant");

        if (cmd == "?") {
            long long c, d;
            if (!(cin >> c >> d)) finish(_pe, "malformed query (expected two integers)");
            if (c < 0 || d < 0 || c >= LIM30 || d >= LIM30) finish(_pe, "query values out of range");

            if (!chosen) {
                if (adaptive_mode) choose_hidden_from_first_query(c, d);
                else finish(_pe, "internal: hidden not chosen in non-adaptive mode");
            }

            queries++;
            if (queries > hard_cap) finish(_pe, "too many queries (hard cap exceeded)");

            uint32_t x = hidden_a ^ (uint32_t)c;
            uint32_t y = hidden_b ^ (uint32_t)d;
            int ans = (x > y) ? 1 : (x < y ? -1 : 0);

            cout << ans << "\n";
            cout.flush();
        } else if (cmd == "!") {
            long long ga, gb;
            if (!(cin >> ga >> gb)) finish(_pe, "malformed answer (expected two integers)");
            if (ga < 0 || gb < 0 || ga >= LIM30 || gb >= LIM30) finish(_pe, "answer values out of range");

            if (!chosen) {
                if (adaptive_mode) choose_hidden_from_first_query(0, 0);
                else finish(_pe, "internal: hidden not chosen in non-adaptive mode");
            }

            if ((uint32_t)ga == hidden_a && (uint32_t)gb == hidden_b) finish(_ok, "correct");
            finish(_wa, "wrong answer");
        } else {
            finish(_pe, "unknown command token");
        }
    }
}


Test generator (C++):
#include "testlib.h"
#include <bits/stdc++.h>
using namespace std;

int main(int argc, char** argv) {
    registerGen(argc, argv, 1);

    string mode = opt<string>("mode", "non");
    int bits = opt<int>("bits", 30);
    ensuref(1 <= bits && bits <= 30, "bits must be in [1, 30]");

    long long LIM = 1LL << bits;

    if (mode == "adp") {
        cout << bits << "\n";
        return 0;
    }

    ensuref(mode == "non", "unknown mode (expected 'non' or 'adp')");

    long long seedVal = 0;
    if (argc > 1 && argv[1]) seedVal = atoll(argv[1]);

    long long a = 0, b = 0;

    if (seedVal == 1) {
        a = 0;
        b = 0;
    } else if (seedVal == 2) {
        a = LIM - 1;
        b = 0;
    } else if (seedVal == 3) {
        a = 1LL << (bits - 1);
        b = a - 1;
    } else {
        int pat = rnd.next(0, 6);
        if (bits < 2 && pat == 6) pat = 0;

        switch (pat) {
            case 0: {
                a = rnd.next(0LL, LIM - 1);
                b = rnd.next(0LL, LIM - 1);
                break;
            }
            case 1: {
                a = rnd.next(0LL, LIM - 1);
                b = a;
                break;
            }
            case 2: {
                int maxLow = min(3, bits);
                int lowBits = rnd.next(1, maxLow);
                int prefixLen = bits - lowBits;

                long long prefixMax = (prefixLen == 0) ? 0LL : ((1LL << prefixLen) - 1);
                long long prefix = rnd.next(0LL, prefixMax);

                long long lowMax = (1LL << lowBits) - 1;
                a = (prefix << lowBits) | rnd.next(0LL, lowMax);
                b = (prefix << lowBits) | rnd.next(0LL, lowMax);
                if (a == b) b ^= 1;
                break;
            }
            case 3: {
                long long alt = 0;
                for (int i = 0; i < bits; i++) if (i & 1) alt |= (1LL << i);

                long long x = rnd.next(0LL, LIM - 1);
                long long y = rnd.next(0LL, LIM - 1);

                a = (alt ^ x) & (LIM - 1);
                b = ((alt >> 1) ^ y) & (LIM - 1);
                break;
            }
            case 4: {
                a = rnd.next(0LL, LIM - 1);
                b = (LIM - 1) ^ a;
                break;
            }
            case 5: {
                a = rnd.next(0LL, LIM - 1);
                long long delta = (long long)rnd.next(-32, 32);
                long long bb = (a + delta) % LIM;
                if (bb < 0) bb += LIM;
                b = bb;
                break;
            }
            case 6: {
                int kLo = max(1, bits - 5);
                int kHi = bits - 1;
                int k = rnd.next(kLo, kHi);

                long long high = (LIM - 1) ^ ((1LL << k) - 1);
                long long lowMax = (1LL << k) - 1;

                a = high | rnd.next(0LL, lowMax);
                b = high | rnd.next(0LL, lowMax);
                if (a == b) b ^= 1;
                break;
            }
        }

        if (rnd.next(0, 3) == 0) swap(a, b);
    }

    a &= (LIM - 1);
    b &= (LIM - 1);
    ensuref(0 <= a && a < LIM && 0 <= b && b < LIM, "generated (a,b) out of bounds");

    cout << a << " " << b << "\n";
    return 0;
}