Problem: cf1103_b
Difficulty: easy
Categories: search
Time limit: 1000 ms, memory limit: 256 MB

This is an interactive problem.

Vasya and Petya are going to play the following game: Petya has some positive integer number $a$. After that Vasya should guess this number using the following questions. He can say a pair of non-negative integer numbers $(x, y)$. Petya will answer him:

* "x", if $(x \bmod a) \geq (y \bmod a)$.
* "y", if $(x \bmod a) < (y \bmod a)$.

We define $(x \bmod a)$ as a remainder of division $x$ by $a$.

Vasya should guess the number $a$ using no more, than 60 questions.

It's guaranteed that Petya has a number, that satisfies the inequality $1 \leq a \leq 10^9$.

Help Vasya playing this game and write a program, that will guess the number $a$.

Interaction

Your program should play several games.

Before the start of any game your program should read the string:

* "start" (without quotes) — the start of the new game.
* "mistake" (without quotes) — in the previous game, you found the wrong answer. Your program should terminate after reading this string and it will get verdict "Wrong answer".
* "end" (without quotes) — all games finished. Your program should terminate after reading this string.

After reading the string "start" (without quotes) the new game starts.

At the beginning, your program should ask several questions about pairs of non-negative integer numbers $(x, y)$. You can only ask the numbers, that satisfy the inequalities $0 \leq x, y \leq 2 \cdot 10^9$. To ask a question print "? x y" (without quotes). As the answer, you should read one symbol:

* "x" (without quotes), if $(x \bmod a) \geq (y \bmod a)$.
* "y" (without quotes), if $(x \bmod a) < (y \bmod a)$.
* "e" (without quotes) — you asked more than $60$ questions. Your program should terminate after reading this string and it will get verdict "Wrong answer".

After your program asked several questions your program should print the answer in form "! a" (without quotes). You should print the number $a$ satisfying the inequalities $1 \leq a \leq 10^9$. It's guaranteed that Petya's number $a$ satisfied this condition. After that, the current game will finish.

We recall that your program can't ask more than $60$ questions during one game.

If your program doesn't terminate after reading "mistake" (without quotes), "end" (without quotes) or "e" (without quotes), it can get any verdict, because it will continue reading from closed input. Also, if your program prints answer or question in the incorrect format it can get any verdict, too. Be careful.

Don't forget to flush the output after printing questions and answers.

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.

It's guaranteed that you should play at least $1$ and no more than $100$ games.

Example

Input

```
start
x
x
start
x
x
y
start
x
x
y
y
end
```

Output

```
? 0 0
? 10 1
! 1
? 0 0
? 3 4
? 2 5
! 2
? 2 4
? 2 5
? 3 10
? 9 1
! 3
```

Note

In the first test, you should play $3$ games with Petya's numbers $1$, $2$ and $3$.

In the first game, Petya will answer "x" (without quotes) to any question, because $(x \bmod 1) = 0$ for any integer $x$.

In the second game, if you will ask pair $(0, 0)$, the answer will be "x" (without quotes), because $(0 \bmod 2) \geq (0 \bmod 2)$. But if you will ask pair $(2, 5)$, the answer will be "y" (without quotes), because $(2 \bmod 2) < (5 \bmod 2)$, because $(2 \bmod 2) = 0$ and $(5 \bmod 2) = 1$.

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 parseLongLong(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;
    }
    __int128 val = 0;
    for (; i < (int)s.size(); i++) {
        char c = s[i];
        if (c < '0' || c > '9') return false;
        val = val * 10 + (c - '0');
        if (val > (__int128)LLONG_MAX + 1) return false;
    }
    if (neg) val = -val;
    if (val < (__int128)LLONG_MIN || val > (__int128)LLONG_MAX) return false;
    out = (long long)val;
    return true;
}

static string readTokenOrPE(const string& what) {
    string t;
    if (!(cin >> t)) finish(_pe, "Unexpected EOF while reading " + what);
    return t;
}

static long long readLLOrPE(const string& what) {
    string s = readTokenOrPE(what);
    long long v = 0;
    if (!parseLongLong(s, v)) finish(_pe, "Malformed integer for " + what);
    return v;
}

static void sendLine(const string& s) {
    cout << s << "\n";
    cout.flush();
}

static void play_one_game(long long a, bool last_game, long long hard_cap) {
    sendLine("start");

    long long game_queries = 0;

    while (true) {
        string cmd = readTokenOrPE("command");

        if (cmd == "?") {
            long long x = readLLOrPE("x");
            long long y = readLLOrPE("y");

            if (x < 0 || y < 0 || x > 2000000000LL || y > 2000000000LL) {
                finish(_pe, "Query numbers out of allowed range");
            }

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

            long long rx = x % a;
            long long ry = y % a;
            char ans = (rx >= ry) ? 'x' : 'y';
            cout << ans << "\n";
            cout.flush();
        } else if (cmd == "!") {
            long long guess = readLLOrPE("answer");
            if (guess < 1 || guess > 1000000000LL) finish(_pe, "Answer out of allowed range");

            if (guess != a) {
                sendLine("mistake");
                finish(_wa, "Wrong guessed a");
            }

            if (last_game) {
                sendLine("end");
                finish(_ok, "OK");
            }
            return; 
        } else {
            finish(_pe, "Invalid command token");
        }
    }
}

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

    int T = inf.readInt(1, 100, "T");
    vector<long long> a(T);
    for (int i = 0; i < T; i++) {
        a[i] = inf.readLong(1LL, 1000000000LL, "a");
    }

    query_limit = 60LL * T;
    log_metrics(); 

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

    for (int i = 0; i < T; i++) {
        play_one_game(a[i], i + 1 == T, hard_cap);
    }

    
    finish(_ok, "OK");
}


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

struct Interval {
    int l, r; 
};

static long long queries = 0;
static long long query_limit = 0;
static long long hard_cap = 200000;

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[0] == '-') {
        neg = true;
        i = 1;
    }
    if (i == (int)s.size()) return false;
    for (int j = i; j < (int)s.size(); j++) {
        if (s[j] < '0' || s[j] > '9') return false;
    }
    if ((int)s.size() > 20) return false;
    try {
        size_t pos = 0;
        long long v = stoll(s, &pos, 10);
        if (pos != s.size()) return false;
        out = v;
        (void)neg;
        return true;
    } catch (...) {
        return false;
    }
}

static long long floor_div(long long a, long long b_pos) {
    
    if (b_pos <= 0) throw runtime_error("floor_div: non-positive denominator");
    long long q = a / b_pos;
    long long r = a % b_pos;
    if (r != 0 && a < 0) q -= 1;
    return q;
}

static long long ceil_div(long long a, long long b_pos) {
    
    if (b_pos <= 0) throw runtime_error("ceil_div: non-positive denominator");
    return -floor_div(-a, b_pos);
}

static void addInterval(vector<Interval>& v, long long l, long long r) {
    if (l > r) return;
    if (l < 1) l = 1;
    if (r > 1000000000LL) r = 1000000000LL;
    if (l > r) return;
    int L = (int)l, R = (int)r;
    if (!v.empty() && (long long)v.back().r + 1 >= L) {
        v.back().r = max(v.back().r, R);
    } else {
        v.push_back({L, R});
    }
}

static long long countIntegers(const vector<Interval>& v) {
    long long s = 0;
    for (const auto& it : v) {
        s += (long long)it.r - (long long)it.l + 1LL;
    }
    return s;
}

static vector<Interval> filterByAnswer(const vector<Interval>& feasible, long long x, long long y, bool wantX) {
    vector<Interval> res;
    res.reserve(feasible.size());

    for (const auto& seg : feasible) {
        long long L = seg.l, R = seg.r;
        long long a = L;
        while (a <= R) {
            long long qx = (a <= x ? x / a : 0);
            long long qy = (a <= y ? y / a : 0);

            long long nextX = (qx == 0 ? R : min(R, x / qx));
            long long nextY = (qy == 0 ? R : min(R, y / qy));
            long long segR = min(nextX, nextY);

            long long dV = x - y;
            long long dQ = qx - qy;

            long long takeL = 1, takeR = 0; 
            if (wantX) {
                
                if (dQ == 0) {
                    if (dV >= 0) {
                        takeL = a;
                        takeR = segR;
                    }
                } else if (dQ > 0) {
                    if (dV >= 0) {
                        long long ub = floor_div(dV, dQ);
                        takeL = a;
                        takeR = min(segR, ub);
                    }
                } else { 
                    long long p = -dQ;
                    long long lb = ceil_div(-dV, p);
                    takeL = max(a, lb);
                    takeR = segR;
                }
            } else {
                
                if (dQ == 0) {
                    if (dV < 0) {
                        takeL = a;
                        takeR = segR;
                    }
                } else if (dQ > 0) {
                    long long lb = floor_div(dV, dQ) + 1;
                    takeL = max(a, lb);
                    takeR = segR;
                } else { 
                    long long p = -dQ;     
                    long long N = -dV;     
                    if (N > 0) {
                        long long ub = floor_div(N - 1, p);
                        takeL = a;
                        takeR = min(segR, ub);
                    }
                }
            }

            if (takeL <= takeR) addInterval(res, takeL, takeR);

            if (segR == R) break;
            a = segR + 1;
        }
    }

    return res;
}

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

    int T = inf.readInt();
    if (T < 1 || T > 100) finish(_pe, "bad T in input");

    string dummy = inf.readLine(); 

    vector<pair<int,int>> ranges;
    ranges.reserve(T);
    for (int i = 0; i < T; i++) {
        string line;
        do {
            if (inf.eof()) finish(_pe, "unexpected EOF while reading games");
            line = inf.readLine();
        } while (line.size() == 0);

        stringstream ss(line);
        long long a, b;
        if (!(ss >> a)) finish(_pe, "bad game line (no number)");
        if (ss >> b) {
            
        } else {
            
            b = a;
        }

        if (a < 1) a = 1;
        if (b < 1) b = 1;
        if (a > 1000000000LL) a = 1000000000LL;
        if (b > 1000000000LL) b = 1000000000LL;
        if (a > b) swap(a, b);
        ranges.push_back({(int)a, (int)b});
    }

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

    
    log_metrics();

    for (int game = 0; game < T; game++) {
        cout << "start" << endl;

        vector<Interval> feasible;
        feasible.push_back({ranges[game].first, ranges[game].second});

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

            if (cmd == "?") {
                string sx, sy;
                if (!(cin >> sx >> sy)) finish(_pe, "bad query format");
                long long x, y;
                if (!parseLongLongStrict(sx, x) || !parseLongLongStrict(sy, y)) finish(_pe, "non-integer in query");
                if (x < 0 || y < 0 || x > 2000000000LL || y > 2000000000LL) finish(_pe, "query out of range");

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

                if (feasible.empty()) finish(_pe, "internal error: empty feasible set");

                vector<Interval> keepX = filterByAnswer(feasible, x, y, true);
                vector<Interval> keepY = filterByAnswer(feasible, x, y, false);

                long long cntX = countIntegers(keepX);
                long long cntY = countIntegers(keepY);

                if (cntX == 0 && cntY == 0) finish(_pe, "internal error: both branches empty");

                char ans;
                if (cntX > cntY) {
                    ans = 'x';
                    feasible.swap(keepX);
                } else if (cntY > cntX) {
                    ans = 'y';
                    feasible.swap(keepY);
                } else {
                    
                    ans = (cntX > 0 ? 'x' : 'y');
                    if (ans == 'x') feasible.swap(keepX);
                    else feasible.swap(keepY);
                }

                cout << ans << endl;
                
                log_metrics();
            } else if (cmd == "!") {
                string sa;
                if (!(cin >> sa)) finish(_pe, "bad answer format");
                long long guess;
                if (!parseLongLongStrict(sa, guess)) finish(_pe, "non-integer answer");
                if (guess < 1 || guess > 1000000000LL) finish(_pe, "answer out of range");
                if (feasible.empty()) finish(_pe, "internal error: empty feasible set at answer");

                
                
                bool ok = false;
                if (feasible.size() == 1 && feasible[0].l == feasible[0].r && feasible[0].l == (int)guess) {
                    ok = true;
                }

                if (!ok) finish(_wa, "answer is not uniquely determined / wrong under some feasible instance");
                break; 
            } else {
                finish(_pe, "unknown command token");
            }
        }
    }

    cout << "end" << endl;
    finish(_ok, "all games finished");
}


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

static long long clampA(long long a) {
    if (a < 1) return 1;
    if (a > 1000000000LL) return 1000000000LL;
    return a;
}

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

    string mode = opt<string>("mode", "non");
    long long seed = 0;
    if (argc >= 2) seed = atoll(argv[1]);

    if (mode == "non") {
        int T = opt<int>("t", (seed >= 1 && seed <= 3) ? 9 : 99);
        if (T < 1) T = 1;
        if (T > 99) T = 99; 

        vector<long long> a;
        a.reserve(T);

        vector<long long> preset;
        if (seed == 1) {
            preset = {1, 2, 3, 4, 5, 999999937LL, 1000000000LL, 536870912LL, 268435455LL};
        } else if (seed == 2) {
            preset = {1, 6, 7, 8, 9, 10, 536870912LL, 536870913LL, 999999937LL};
        } else if (seed == 3) {
            preset = {1, 2, 999983LL, 720720LL, 500000000LL, 500000001LL, 999999929LL, 999999937LL, 1000000000LL};
        } else {
            preset = {
                1, 2, 3, 4, 5, 7, 8, 9, 10,
                999999937LL, 999999929LL, 1000000000LL,
                536870912LL, 268435455LL, 268435456LL, 268435457LL,
                500000000LL, 500000001LL, 999983LL, 720720LL
            };
        }

        unordered_set<long long> used;
        used.reserve((size_t)T * 2 + 64);

        for (long long v : preset) {
            if ((int)a.size() >= T) break;
            v = clampA(v);
            if (!used.count(v)) {
                used.insert(v);
                a.push_back(v);
            }
        }

        int attempts = 0;
        while ((int)a.size() < T && attempts < 200000) {
            ++attempts;
            int typ = rnd.next(0, 3);
            long long v = 1;

            if (typ == 0) {
                
                v = rnd.next(1LL, 1000LL);
            } else if (typ == 1) {
                
                int k = rnd.next(0, 29);
                v = (1LL << k);
                long long delta = rnd.next(-3LL, 3LL);
                v = clampA(v + delta);
            } else if (typ == 2) {
                
                v = 1000000000LL - rnd.next(0LL, 300000LL);
                v = clampA(v);
            } else {
                
                v = rnd.next(1LL, 1000000000LL);
            }

            if (!used.count(v)) {
                used.insert(v);
                a.push_back(v);
            }
        }

        
        while ((int)a.size() < T) a.push_back(1);

        cout << T << "\n";
        for (int i = 0; i < T; i++) {
            cout << a[i] << "\n";
        }
        return 0;
    }

    if (mode == "adp") {
        int T = opt<int>("t", (seed >= 1 && seed <= 3) ? 8 : 100);
        if (T < 1) T = 1;
        if (T > 100) T = 100;

        long long defL = opt<long long>("l", 1LL);
        long long defR = opt<long long>("r", 1000000000LL);
        if (defL < 1) defL = 1;
        if (defR > 1000000000LL) defR = 1000000000LL;
        if (defL > defR) swap(defL, defR);

        vector<pair<long long, long long>> ranges;
        ranges.reserve(T);

        if (seed == 1) {
            vector<pair<long long, long long>> p = {
                {1, 1}, {2, 2}, {1000000000LL, 1000000000LL}, {999999937LL, 999999937LL},
                {1, 2}, {536870912LL, 536870912LL}, {268435455LL, 268435455LL}, {1, 1000000000LL}
            };
            for (int i = 0; i < T; i++) ranges.push_back(p[i % (int)p.size()]);
        } else if (seed == 2) {
            vector<pair<long long, long long>> p = {
                {1, 2}, {2, 3}, {3, 5}, {999999900LL, 1000000000LL},
                {536870900LL, 536870930LL}, {268435440LL, 268435470LL}, {1, 1000000000LL}, {999999937LL, 999999937LL}
            };
            for (int i = 0; i < T; i++) ranges.push_back(p[i % (int)p.size()]);
        } else if (seed == 3) {
            vector<pair<long long, long long>> p = {
                {1, 1000000000LL}, {1, 1000}, {999000000LL, 1000000000LL}, {1, 2},
                {500000000LL, 500000010LL}, {720720LL, 720720LL}, {999983LL, 1000000LL}, {268435455LL, 268435457LL}
            };
            for (int i = 0; i < T; i++) ranges.push_back(p[i % (int)p.size()]);
        } else {
            
            
            for (int i = 0; i < T; i++) {
                int typ = (i % 5);
                long long L = defL, R = defR;
                if (typ == 0) {
                    L = 1; R = 1000000000LL;
                } else if (typ == 1) {
                    long long width = rnd.next(0LL, 5000LL);
                    L = 1000000000LL - rnd.next(0LL, 200000LL);
                    R = clampA(L + width);
                    L = clampA(L);
                    if (L > R) swap(L, R);
                } else if (typ == 2) {
                    int k = rnd.next(0, 29);
                    long long center = (1LL << k);
                    long long w = rnd.next(0LL, 20LL);
                    L = clampA(center - w);
                    R = clampA(center + w);
                    if (L > R) swap(L, R);
                } else if (typ == 3) {
                    long long x = rnd.next(1LL, 1000000000LL);
                    L = x; R = x; 
                } else {
                    L = defL; R = defR;
                }
                ranges.push_back({L, R});
            }
        }

        cout << T << "\n";
        for (int i = 0; i < T; i++) {
            cout << ranges[i].first << " " << ranges[i].second << "\n";
        }
        return 0;
    }

    
    cout << 1 << "\n" << 999999937LL << "\n";
    return 0;
}