Problem: cf1482_g
Difficulty: medium
Categories: game, greedy, search
Time limit: 2000 ms, memory limit: 256 MB

Gustaw is the chief bank manager in a huge bank. He has unlimited access to the database system of the bank, in a few clicks he can move any amount of money from the bank's reserves to his own private account. However, the bank uses some fancy AI fraud detection system that makes stealing more difficult.

Gustaw knows that the anti-fraud system just detects any operation that exceeds some fixed limit $M$ euros and these operations are checked manually by a number of clerks. Thus, any fraud operation exceeding this limit is detected, while any smaller operation gets unnoticed.

Gustaw doesn't know the limit $M$ and wants to find it out. In one operation, he can choose some integer $X$ and try to move $X$ euros from the bank's reserves to his own account. Then, the following happens.

* If $X \le M$, the operation is unnoticed and Gustaw's account balance raises by $X$ euros.
* Otherwise, if $X > M$, the fraud is detected and cancelled. Moreover, Gustaw has to pay $X$ euros from his own account as a fine. If he has less than $X$ euros on the account, he is fired and taken to the police.

Initially Gustaw has $1$ euro on his account. Help him find the exact value of $M$ in no more than $105$ operations without getting him fired.

Input

Each test contains multiple test cases. The first line contains the number of test cases $t$ ($1 \le t \le 1000$).

For each test case, there is no input prior to your first query, but you can be sure that $M$ is integer, and $0 \le M \le 10^{14}$.

Output

For each test case, when you know the exact value of $M$, print a single line with format "! $M$". After that your program should proceed to the next test case or terminate, if it is the last one.

Interaction

When you want to make an operation, print a single line with format "? $X$", denoting that you try to move $X$ euros ($1 \le X \le 10^{14}$). As a response, read a single line that can take the following values:

* "Lucky!", if $X \le M$. Your balance raises by $X$.
* "Fraudster!", if $X > M$. Your balance decreases by $X$.
* "Fired!", if $X > M$, but you can't pay $X$ euros of fine. In this case your program must terminate immediately. You also get this response if you exceed the number of queries.

You can make at most $105$ such queries in each test case.

After printing a query do not forget to output end of line and flush the output. Otherwise, you will get Idleness limit exceeded. To do this, use:

* fflush(stdout) or cout.flush() in C++;
* System.out.flush() in Java;
* flush(output) in Pascal;
* stdout.flush() in Python;
* see documentation for other languages.

Example

Input

```
1

Lucky!

Lucky!

Lucky!

Lucky!

Lucky!

Fraudster!
```

Output

```
? 1

? 2

? 3

? 4

? 5

? 6

! 5
```

Note

In the example $M = 5$, so the operation with $X = 6$ is detected. At this moment, Gustaw's balance is $16$ euros, so he just pays fine.

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 parseNonNegLL(const string& s, long long& out) {
    if (s.empty()) return false;
    __int128 v = 0;
    for (char c : s) {
        if (c < '0' || c > '9') return false;
        v = v * 10 + (c - '0');
        if (v > (__int128)LLONG_MAX) return false;
    }
    out = (long long)v;
    return true;
}

static bool readToken(string& tok) {
    return (cin >> tok) ? true : false;
}

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

    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    const long long MIN_M = 0;
    const long long MAX_M = 100000000000000LL; 
    const long long MIN_X = 1;
    const long long MAX_X = 100000000000000LL; 
    const long long PER_CASE_LIMIT = 100000; 

    int t = inf.readInt(1, 1000, "t");
    vector<long long> vals;
    while (!inf.seekEof()) {
        vals.push_back(inf.readLong(MIN_M, MAX_M, "val"));
    }

    bool adaptive = false;
    if ((int)vals.size() == t) adaptive = false;
    else if ((int)vals.size() == 2 * t) adaptive = true;
    else {
        query_limit = PER_CASE_LIMIT * 1LL * max(1, t);
        log_metrics();
        finish(_pe, "bad hidden input: expected t numbers (non) or 2*t numbers (adp)");
    }

    query_limit = PER_CASE_LIMIT * 1LL * t;
    log_metrics(); 

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

    cout << t << "\n";
    cout.flush();

    for (int tc = 0; tc < t; tc++) {
        long long lo, hi;
        if (!adaptive) {
            lo = hi = vals[tc];
        } else {
            lo = vals[2 * tc];
            hi = vals[2 * tc + 1];
        }

        if (!(MIN_M <= lo && lo <= hi && hi <= MAX_M)) {
            finish(_pe, "bad hidden input interval/value out of range");
        }

        __int128 bal = 1;
        long long used_tc = 0;

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

            string tok;
            if (!readToken(tok)) {
                finish(_pe, "unexpected EOF from contestant");
            }

            char type = 0;
            string rest;
            if (!tok.empty() && (tok[0] == '?' || tok[0] == '!')) {
                type = tok[0];
                rest = tok.substr(1);
            } else {
                finish(_pe, "invalid token (expected ? or !)");
            }

            if (type == '?') {
                string numTok;
                if (!rest.empty()) numTok = rest;
                else {
                    if (!readToken(numTok)) finish(_pe, "expected X after ?");
                }

                long long X;
                if (!parseNonNegLL(numTok, X)) finish(_pe, "X is not a non-negative integer");
                if (X < MIN_X || X > MAX_X) finish(_pe, "X out of allowed range");

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

                if (used_tc > PER_CASE_LIMIT) {
                    cout << "Fired!\n";
                    cout.flush();
                    finish(_wa, "query limit exceeded");
                }

                bool mustLucky = (lo >= X);
                bool mustFraud = (hi < X);

                string reply;
                if (mustLucky) {
                    reply = "Lucky!";
                    lo = max(lo, X);
                    bal += (__int128)X;
                } else if (mustFraud) {
                    if (bal < (__int128)X) {
                        cout << "Fired!\n";
                        cout.flush();
                        finish(_wa, "fired: insufficient balance to pay fine");
                    }
                    reply = "Fraudster!";
                    hi = min(hi, X - 1);
                    bal -= (__int128)X;
                } else {
                    
                    if (bal < (__int128)X) {
                        reply = "Lucky!";
                        lo = max(lo, X);
                        bal += (__int128)X;
                    } else {
                        long long loL = max(lo, X), hiL = hi;
                        long long loF = lo, hiF = min(hi, X - 1);

                        __int128 lenL = (loL <= hiL) ? (__int128)(hiL - loL + 1) : 0;
                        __int128 lenF = (loF <= hiF) ? (__int128)(hiF - loF + 1) : 0;

                        bool chooseFraud = false;
                        if (lenF > lenL) chooseFraud = true;
                        else if (lenF < lenL) chooseFraud = false;
                        else chooseFraud = true; 

                        if (chooseFraud) {
                            reply = "Fraudster!";
                            hi = hiF;
                            bal -= (__int128)X;
                        } else {
                            reply = "Lucky!";
                            lo = loL;
                            bal += (__int128)X;
                        }
                    }
                }

                if (lo > hi) finish(_pe, "internal error: feasible interval became empty");
                if (bal < 0) finish(_pe, "internal error: negative balance without firing");

                cout << reply << "\n";
                cout.flush();
            } else { 
                string numTok;
                if (!rest.empty()) numTok = rest;
                else {
                    if (!readToken(numTok)) finish(_pe, "expected M after !");
                }

                long long ans;
                if (!parseNonNegLL(numTok, ans)) finish(_pe, "answer is not a non-negative integer");
                if (ans < MIN_M || ans > MAX_M) finish(_pe, "answer out of allowed range");

                if (ans < lo || ans > hi) finish(_wa, "wrong answer: not consistent with interaction");
                if (lo != hi) finish(_wa, "wrong answer: M not uniquely determined");
                break;
            }
        }
    }

    finish(_ok, "OK");
}


Adaptive interactor (C++):

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

static long long clampLL(long long x, long long lo, long long hi) {
    if (x < lo) return lo;
    if (x > hi) return hi;
    return x;
}

static vector<long long> buildSpecials(long long minM, long long maxM) {
    vector<long long> s;
    auto add = [&](long long x) {
        if (x < minM || x > maxM) return;
        s.push_back(x);
    };

    
    add(minM);
    add(minM + 1);
    add(minM + 2);
    add(1);
    add(2);
    add(3);
    add(4);
    add(5);
    add(6);
    add(7);
    add(8);
    add(9);
    add(10);

    add(maxM);
    add(maxM - 1);
    add(maxM - 2);
    add(maxM - 3);
    add(maxM - 4);
    add(maxM - 5);

    add(maxM / 2);
    add(maxM / 2 - 1);
    add(maxM / 2 + 1);

    
    __int128 p10 = 1;
    for (int k = 0; k <= 14; k++) {
        long long v = (long long)p10;
        add(v - 1);
        add(v);
        add(v + 1);
        if (v <= maxM) {
            add(maxM - v);
            add(maxM - v - 1);
            add(maxM - v + 1);
        }
        p10 *= 10;
        if (p10 > (__int128)maxM + 100) break;
    }

    
    for (int e = 0; e <= 62; e++) {
        __int128 p = (__int128)1 << e;
        if (p > (__int128)maxM + 2) break;
        long long pv = (long long)p;
        add(pv - 2);
        add(pv - 1);
        add(pv);
        add(pv + 1);
        add(pv + 2);
        add(pv * 3 / 2); 
        add(pv * 2 - 1);
        add(pv * 2);
        add(pv * 2 + 1);
    }

    
    add(99999999999999LL);
    add(99999999999998LL);
    add(99999999999997LL);
    add(10000000000000LL);
    add(10000000000001LL);
    add(50000000000000LL);
    add(33333333333333LL);
    add(66666666666666LL);
    add(77777777777777LL);
    add(22222222222222LL);
    add(12345678901234LL);
    add(98765432109876LL);

    
    add(maxM / 4);
    add(maxM / 4 - 1);
    add(maxM / 4 + 1);
    add((maxM * 3) / 4);
    add((maxM * 3) / 4 - 1);
    add((maxM * 3) / 4 + 1);

    
    return s;
}

static long long genRandomM(long long minM, long long maxM, const vector<long long>& specials) {
    int type = rnd.next(0, 99);

    auto nearVal = [&](long long center, long long spread) -> long long {
        long long delta = rnd.next(-spread, spread);
        return clampLL(center + delta, minM, maxM);
    };

    if (type < 30) {
        return rnd.next(minM, maxM); 
    } else if (type < 45) {
        
        long long spread = rnd.next(0LL, 2000000LL);
        return clampLL(maxM - spread, minM, maxM);
    } else if (type < 55) {
        
        long long spread = rnd.next(0LL, 2000000LL);
        return clampLL(minM + spread, minM, maxM);
    } else if (type < 70) {
        
        int e = rnd.next(0, 47);
        long long p = (e >= 0 && e < 62) ? (1LL << e) : 1LL;
        if (p > maxM) p = maxM;
        long long d = rnd.next(-3LL, 3LL);
        return clampLL(p + d, minM, maxM);
    } else if (type < 82) {
        
        int k = rnd.next(0, 14);
        __int128 p10 = 1;
        for (int i = 0; i < k; i++) p10 *= 10;
        long long base = (p10 > (__int128)maxM) ? maxM : (long long)p10;
        long long d = rnd.next(-5LL, 5LL);
        return clampLL(base + d, minM, maxM);
    } else if (type < 90) {
        
        int e = rnd.next(0, 47);
        long long base = (e == 0) ? 0LL : ((1LL << e) - 1);
        if (base > maxM) base = maxM;
        long long room = maxM - base;
        long long extra = 0;
        if (room > 0) {
            long long lim = min(room, (1LL << min(20, e)) - 1);
            extra = rnd.next(0LL, lim);
        }
        return clampLL(base + extra, minM, maxM);
    } else {
        
        long long pick = specials.empty() ? rnd.next(minM, maxM) : specials[rnd.next(0, (int)specials.size() - 1)];
        long long spread = rnd.next(0LL, 10000000LL);
        return nearVal(pick, spread);
    }
}

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

    string mode = opt<string>("mode", "non");
    int t = opt<int>("t", 1000);
    long long minM = opt<long long>("minM", 0LL);
    long long maxM = opt<long long>("maxM", 100000000000000LL);

    ensuref(1 <= t && t <= 1000, "t must be in [1..1000]");
    ensuref(0LL <= minM && minM <= maxM, "require 0 <= minM <= maxM");
    ensuref(maxM <= 100000000000000LL, "maxM must be <= 1e14");

    long long seed = 0;
    if (argc >= 2) seed = atoll(argv[1]);

    vector<long long> specials = buildSpecials(minM, maxM);

    cout << t << "\n";

    if (mode == "non") {
        vector<long long> M(t, minM);

        int offset = 0;
        if (!specials.empty()) offset = (int)(seed % (long long)specials.size());

        
        for (int i = 0; i < t; i++) {
            if (seed == 1) {
                
                if (i % 50 == 0) M[i] = 0;
                else if (i % 50 == 1) M[i] = 1;
                else if (i % 50 == 2) M[i] = maxM;
                else if (i % 50 == 3) M[i] = maxM - 1;
                else if (i < (int)specials.size()) M[i] = specials[(i + offset) % specials.size()];
                else M[i] = genRandomM(minM, maxM, specials);
            } else if (seed == 2) {
                
                if (i < 25) M[i] = clampLL(i, minM, maxM);
                else if (i % 40 == 0) M[i] = 0;
                else if (i % 40 == 1) M[i] = 2;
                else if (i % 40 == 2) M[i] = 3;
                else if (i % 40 == 3) M[i] = 4;
                else if (i % 40 == 4) M[i] = 7;
                else if (i % 40 == 5) M[i] = 8;
                else if (i % 40 == 6) M[i] = 15;
                else if (i % 40 == 7) M[i] = 16;
                else if (i % 40 == 8) M[i] = 31;
                else if (i % 40 == 9) M[i] = 32;
                else if (i < (int)specials.size()) M[i] = specials[(i * 7 + offset) % specials.size()];
                else M[i] = genRandomM(minM, maxM, specials);
            } else if (seed == 3) {
                
                if (i < 60) M[i] = clampLL(maxM - i, minM, maxM);
                else if (i % 37 == 0) M[i] = maxM;
                else if (i % 37 == 1) M[i] = maxM - 1;
                else if (i % 37 == 2) M[i] = maxM / 2;
                else if (i % 37 == 3) M[i] = (1LL << 46) - 1; 
                else if (i % 37 == 4) M[i] = (1LL << 46);
                else if (i % 37 == 5) M[i] = (1LL << 45) - 1;
                else if (i < (int)specials.size()) M[i] = specials[(i * 13 + offset) % specials.size()];
                else M[i] = genRandomM(minM, maxM, specials);
            } else {
                
                if (!specials.empty() && i < (int)specials.size() / 2) {
                    M[i] = specials[(i + offset) % specials.size()];
                } else if (i % 64 == 0) {
                    M[i] = 0;
                } else if (i % 64 == 1) {
                    M[i] = maxM;
                } else if (i % 64 == 2) {
                    M[i] = maxM - 1;
                } else if (i % 64 == 3) {
                    M[i] = maxM / 2;
                } else {
                    M[i] = genRandomM(minM, maxM, specials);
                }
            }
        }

        for (int i = 0; i < t; i++) {
            cout << M[i] << "\n";
        }
    } else if (mode == "adp") {
        
        
        for (int i = 0; i < t; i++) {
            long long L = minM, R = maxM;

            if (seed == 1) {
                if (i == 0) { L = 0; R = 0; }
                else if (i == 1) { L = maxM; R = maxM; }
                else if (i == 2) { L = 0; R = 1; }
                else if (i == 3) { L = maxM - 1; R = maxM; }
                else if (i == 4) { L = maxM / 2; R = maxM / 2; }
                else if (i % 20 == 0) { L = 0; R = maxM; }
                else {
                    long long c = specials.empty() ? rnd.next(minM, maxM) : specials[(i * 11) % (int)specials.size()];
                    long long w = rnd.next(0LL, 2000LL);
                    L = clampLL(c - w, minM, maxM);
                    R = clampLL(c + w, minM, maxM);
                }
            } else if (seed == 2) {
                if (i < 10) { L = i; R = i; }
                else if (i % 25 == 0) { L = 0; R = maxM; }
                else {
                    long long c = rnd.next(minM, maxM);
                    long long w = rnd.next(0LL, 100000LL);
                    L = clampLL(c - w, minM, maxM);
                    R = clampLL(c + w, minM, maxM);
                }
            } else if (seed == 3) {
                if (i < 10) { L = clampLL(maxM - i, minM, maxM); R = L; }
                else if (i % 30 == 0) { L = 0; R = maxM; }
                else {
                    long long c = clampLL(maxM - rnd.next(0LL, 5000000LL), minM, maxM);
                    long long w = rnd.next(0LL, 5000LL);
                    L = clampLL(c - w, minM, maxM);
                    R = clampLL(c + w, minM, maxM);
                }
            } else {
                
                int roll = rnd.next(0, 99);
                if (roll < 80) {
                    L = minM; R = maxM;
                } else if (roll < 90) {
                    long long c = specials.empty() ? rnd.next(minM, maxM) : specials[rnd.next(0, (int)specials.size() - 1)];
                    long long w = rnd.next(0LL, 50000LL);
                    L = clampLL(c - w, minM, maxM);
                    R = clampLL(c + w, minM, maxM);
                } else {
                    
                    long long c = genRandomM(minM, maxM, specials);
                    L = c; R = c;
                }
            }

            if (L > R) swap(L, R);
            cout << L << " " << R << "\n";
        }
    } else {
        quitf(_fail, "Unknown --mode value: %s", mode.c_str());
    }

    return 0;
}