Problem: cf1386_a
Difficulty: hard
Categories: search
Time limit: 1000 ms, memory limit: 256 MB

Linda likes to change her hair color from time to time, and would be pleased if her boyfriend Archie would notice the difference between the previous and the new color. Archie always comments on Linda's hair color if and only if he notices a difference — so Linda always knows whether Archie has spotted the difference or not.

There is a new hair dye series in the market where all available colors are numbered by integers from $1$ to $N$ such that a smaller difference of the numerical values also means less visual difference.

Linda assumes that for these series there should be some critical color difference $C$ ($1 \le C \le N$) for which Archie will notice color difference between the current color $\mathrm{color}_{\mathrm{new}}$ and the previous color $\mathrm{color}_{\mathrm{prev}}$ if $\left|\mathrm{color}_{\mathrm{new}} - \mathrm{color}_{\mathrm{prev}}\right| \ge C$ and will not if $\left|\mathrm{color}_{\mathrm{new}} - \mathrm{color}_{\mathrm{prev}}\right| < C$.

Now she has bought $N$ sets of hair dye from the new series — one for each of the colors from $1$ to $N$, and is ready to set up an experiment. Linda will change her hair color on a regular basis and will observe Archie's reaction — whether he will notice the color change or not. Since for the proper dye each set should be used completely, each hair color can be obtained no more than once.

Before the experiment, Linda was using a dye from a different series which is not compatible with the new one, so for the clearness of the experiment Archie's reaction to the first used color is meaningless.

Her aim is to find the precise value of $C$ in a limited number of dyes. Write a program which finds the value of $C$ by experimenting with the given $N$ colors and observing Archie's reactions to color changes.

Interaction

This is an interactive task. In the beginning you are given a single integer $T$ ($1 \leq T \leq 100$), the number of cases in the test.

For each test case, the input first contains a single integer — the value of $N$ ($1 < N \le 10^{18}$). The value of $C$ is kept secret by the grading system.

Then your program should make queries writing output in the following format: "? $P$", where $P$ is an integer ($1 \le P \le N$) denoting the next color used. For each query the grading system gives an answer in the next line of the input. The answer is $1$ if Archie notices the color difference between the last two colors and $0$ otherwise. No two queries should have the same $P$ value.

When your program determines $C$, it should output its value in the following format: "= $C$". The grading system will not respond to this output and will proceed with the next test case.

Your program may use at most 64 queries "?" for each test case to find the correct value of $C$.

To establish proper communication between your program and the grading system, you should flush the output stream after each query.

\begin{array}{ll} \text{Language} & \text{Command} \\ \hline \text{C++} & \texttt{std::cout }\texttt{<}\texttt{<}\texttt{ std::endl;} \\ \text{Java} & \texttt{System.out.flush();} \\ \text{Python} & \texttt{sys.stdout.flush()} \end{array} Flush commands 

Note that std::endl writes a newline and flushes the stream.

It is possible to receive an "Output isn't correct" outcome even after printing a correct answer, if task constraints were violated during the communication. Violating the communication protocol itself may result in an "Execution killed" outcome.

Submitting user tests requires specifying an input file with the testcase parameters. The format of the input file is "$T$" in the first line, and then "$N$ $C$" on a single line for each of the $T$ cases.

Scoring

Subtasks:

1. (9 points) $N \le 64$
2. (13 points) $N \le 125$
3. (21 points) $N \le 1000$
4. (24 points) $N \le 10^9$
5. (33 points) No further constraints.

Example

Input

```
1

7

1

1

0

0

1
```

Output

```
? 2

? 7

? 4

? 1

? 5

= 4
```

Note

Comments to the example input line by line:

1. $N = 7$.
2. Answer to the first query is meaningless (can also be $0$).
3. $C \leq 5$.
4. $3 < C \leq 5$. It would be wise to check difference $4$. However, this can not be done in the next query since $4 + 4 = 8$ and $4 - 4 = 0$ both are outside the allowed interval $1 \le P \le 7$.
5. $3 < C \leq 5$.
6. $3 < C \leq 4$. Therefore, $C = 4$.

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 << endl;
        tout << "query_limit=" << query_limit << endl;
    } catch (...) {
        
    }
}

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

static bool parseLL_strict(const string& s, long long& out) {
    if (s.empty()) return false;
    size_t i = 0;
    if (s[0] == '+') i = 1;
    if (i >= s.size()) return false;
    for (size_t j = i; j < s.size(); j++) if (!isdigit((unsigned char)s[j])) return false;
    try {
        size_t pos = 0;
        long long v = stoll(s, &pos, 10);
        if (pos != s.size()) return false;
        out = v;
        return true;
    } catch (...) {
        return false;
    }
}

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

static long long readLLOrPE(const string& ctx) {
    string s = readTokenOrPE(ctx);
    long long v;
    if (!parseLL_strict(s, v)) finish(_pe, "Expected integer for " + ctx);
    return v;
}

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

    const long long LIM = 1000000000000000000LL;

    int T = (int)inf.readInt(1, 100, "T");
    vector<long long> N(T), C(T);
    for (int tc = 0; tc < T; tc++) {
        N[tc] = inf.readLong(2, LIM, "N");
        C[tc] = inf.readLong(1, N[tc], "C");
    }

    query_limit = 64LL * T;
    log_metrics(); 

    cout << T << "\n";
    for (int tc = 0; tc < T; tc++) cout << N[tc] << "\n";
    cout.flush();

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

    for (int tc = 0; tc < T; tc++) {
        set<long long> used;
        bool hasPrev = false;
        long long prev = -1;

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

            string cmd = readTokenOrPE("command");
            long long val = -1;
            bool hasAttached = false;

            if (!cmd.empty() && (cmd[0] == '?' || cmd[0] == '=')) {
                if (cmd.size() > 1) {
                    string rest = cmd.substr(1);
                    if (!parseLL_strict(rest, val)) finish(_pe, "Invalid attached integer after command");
                    hasAttached = true;
                    cmd = string(1, cmd[0]);
                }
            }

            if (cmd == "?") {
                if (!hasAttached) val = readLLOrPE("P");
                long long P = val;

                if (P < 1 || P > N[tc]) finish(_pe, "Query P out of range");
                if (used.count(P)) finish(_pe, "Duplicate P in queries");
                used.insert(P);

                queries++;

                int ans = 0;
                if (!hasPrev) {
                    ans = 0; 
                    hasPrev = true;
                    prev = P;
                } else {
                    long long diff = llabs(P - prev);
                    ans = (diff >= C[tc]) ? 1 : 0;
                    prev = P;
                }

                cout << ans << "\n";
                cout.flush();
            } else if (cmd == "=") {
                if (!hasAttached) val = readLLOrPE("answer C");
                long long guess = val;

                if (guess < 1 || guess > N[tc]) finish(_wa, "Answer C out of range");
                if (guess != C[tc]) finish(_wa, "Wrong answer");
                break; 
            } else {
                finish(_pe, "Unknown command token");
            }
        }
    }

    
    {
        string extra;
        if (cin >> extra) finish(_pe, "Extra output after finishing all test cases");
    }

    finish(_ok, "OK");
    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 bool parseLongLongStrict(const string& s, long long& out) {
    
    try {
        size_t idx = 0;
        long long v = stoll(s, &idx, 10);
        if (idx != s.size()) return false;
        out = v;
        return true;
    } catch (...) {
        return false;
    }
}

struct HiddenCase {
    long long N = 0;
    bool fixed = false;
    long long C = 0;      
    long long lo = 0, hi = 0; 
};

static inline long long absDiffLL(long long a, long long b) {
    return (a >= b) ? (a - b) : (b - a);
}

static int chooseAdaptiveAnswer(long long lo, long long hi, long long d) {
    
    
    
    
    bool can1 = (lo <= d);
    bool can0 = (d + 1 <= hi);

    if (!can1 && !can0) return -1; 

    if (can1 && !can0) return 1;
    if (!can1 && can0) return 0;

    
    __int128 len1 = (__int128)d - (__int128)lo + 1;      
    __int128 len0 = (__int128)hi - (__int128)d;          
    if (len0 > len1) return 0;
    if (len1 > len0) return 1;

    
    return 0;
}

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

    int T = 0;
    try {
        T = inf.readInt();
    } catch (...) {
        query_limit = 0;
        log_metrics();
        finish(_pe, "failed to read T from hidden input");
    }
    if (T < 1 || T > 100) {
        query_limit = 64LL * max(1, T);
        log_metrics();
        finish(_pe, "invalid T in hidden input");
    }

    
    vector<long long> rest;
    while (!inf.seekEof()) {
        long long x = 0;
        try {
            x = inf.readLong();
        } catch (...) {
            query_limit = 64LL * T;
            log_metrics();
            finish(_pe, "failed to read hidden tokens");
        }
        rest.push_back(x);
    }

    vector<HiddenCase> cases;
    cases.reserve(T);

    if ((long long)rest.size() == 2LL * T) {
        for (int i = 0; i < T; i++) {
            long long N = rest[2LL * i];
            long long C = rest[2LL * i + 1];
            if (!(N > 1 && N <= (long long)1e18)) finish(_pe, "invalid N in hidden input");
            if (!(C >= 1 && C <= N)) finish(_pe, "invalid C in hidden input");
            HiddenCase hc;
            hc.N = N;
            hc.fixed = true;
            hc.C = C;
            hc.lo = hc.hi = C;
            cases.push_back(hc);
        }
    } else if ((long long)rest.size() == 3LL * T) {
        for (int i = 0; i < T; i++) {
            long long N = rest[3LL * i];
            long long L = rest[3LL * i + 1];
            long long R = rest[3LL * i + 2];
            if (!(N > 1 && N <= (long long)1e18)) finish(_pe, "invalid N in hidden input");
            if (!(L >= 1 && L <= R && R <= N)) finish(_pe, "invalid [L,R] in hidden input");
            HiddenCase hc;
            hc.N = N;
            hc.fixed = false;
            hc.lo = L;
            hc.hi = R;
            cases.push_back(hc);
        }
    } else {
        query_limit = 64LL * T;
        log_metrics();
        finish(_pe, "unrecognized hidden input format (expected 2*T or 3*T numbers after T)");
    }

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

    
    log_metrics();

    
    cout << T << endl;

    for (int tc = 0; tc < T; tc++) {
        HiddenCase& hc = cases[tc];

        cout << hc.N << endl;

        long long prevP = -1;
        bool havePrev = false;
        unordered_set<long long> used;
        used.reserve(256);

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

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

            if (cmd == '?') {
                string pstr;
                if (!attached.empty()) {
                    pstr = attached;
                } else {
                    if (!(cin >> pstr)) finish(_pe, "missing P after '?'");
                }

                long long P = 0;
                if (!parseLongLongStrict(pstr, P)) finish(_pe, "P is not a valid integer");
                if (P < 1 || P > hc.N) finish(_pe, "P out of range");
                if (used.find(P) != used.end()) finish(_pe, "repeated P");
                used.insert(P);

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

                int ans = 0;

                if (!havePrev) {
                    
                    ans = 0;
                    havePrev = true;
                    prevP = P;
                } else {
                    long long d = absDiffLL(prevP, P);

                    if (hc.fixed) {
                        ans = (d >= hc.C) ? 1 : 0;
                    } else {
                        int chosen = chooseAdaptiveAnswer(hc.lo, hc.hi, d);
                        if (chosen < 0) {
                            finish(_pe, "internal infeasible state");
                        }
                        ans = chosen;
                        if (ans == 1) {
                            hc.hi = min(hc.hi, d);
                        } else {
                            hc.lo = max(hc.lo, d + 1);
                        }
                        if (hc.lo > hc.hi) {
                            finish(_pe, "internal interval became empty");
                        }
                    }

                    prevP = P;
                }

                cout << ans << endl;
                continue;
            }

            if (cmd == '=' || cmd == '!') {
                string gstr;
                if (!attached.empty()) {
                    gstr = attached;
                } else {
                    if (!(cin >> gstr)) finish(_pe, "missing C after '='/'!'");
                }

                long long G = 0;
                if (!parseLongLongStrict(gstr, G)) finish(_pe, "guessed C is not a valid integer");
                if (G < 1 || G > hc.N) finish(_pe, "guessed C out of range");

                if (hc.fixed) {
                    if (G != hc.C) {
                        finish(_wa, "wrong answer");
                    }
                } else {
                    if (hc.lo != hc.hi || G != hc.lo) {
                        finish(_wa, "wrong answer");
                    }
                }
                break; 
            }

            finish(_pe, "unknown command");
        }
    }

    finish(_ok, "accepted");
}


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");

    
    long long T = opt<long long>("T", 1LL);

    auto pickN = [&](int seed) -> long long {
        
        if (seed == 1) return 2;                  
        if (seed == 2) return 3;                  
        if (seed == 3) return 64;                 
        
        
        long long lo = 1'000'000'000'000LL;       
        long long hi = 1'000'000'000'000'000'000LL; 
        
        int t = rnd.next(0, 9);
        if (t == 0) return 1'000'000'000'000'000'000LL; 
        if (t == 1) return 999'999'999'999'999'937LL;   // near 1e18, prime-ish
        if (t == 2) return (1LL << 59) - 1;             // Mersenne-like (within 1e18)
        if (t == 3) return (1LL << 59);                 // power of two (within 1e18)
        if (t == 4) return 999'999'937'000'000'007LL;   
        
        return rnd.next(lo, hi);
    };

    auto pickC_non = [&](long long N, int seed) -> long long {
        
        if (seed == 1) return 1;       
        if (seed == 2) return 3;       
        if (seed == 3) return 33;      
        
        int t = rnd.next(0, 11);
        if (t == 0) return 1;
        if (t == 1) return N;
        if (t == 2) return max(1LL, N / 2);
        if (t == 3) return min(N, max(1LL, N / 2 + 1));
        if (t == 4) return min(N, 63LL);               
        if (t == 5) return min(N, 64LL);               
        if (t == 6) return min(N, 65LL);               
        if (t == 7) {
            
            long long p = 1;
            while (p < N && p <= (LLONG_MAX / 2)) p <<= 1;
            long long cand = min(N, p);
            return max(1LL, cand);
        }
        if (t == 8) {
            
            long long p = 1;
            while ((p << 1) <= N && p <= (LLONG_MAX / 2)) p <<= 1;
            long long cand = min(N, p - 1);
            return max(1LL, cand);
        }
        if (t == 9) {
            
            long long s = (long long) sqrt((long double)N);
            s = max(1LL, min(N, s));
            return s;
        }
        if (t == 10) {
            
            long long s = (long long) sqrt((long double)N);
            long long cand = N - s;
            return max(1LL, min(N, cand));
        }
        
        return rnd.next(1LL, N);
    };

    auto pickParams_adp = [&](long long N, int seed, long long &L, long long &R) {
        
        
        if (seed == 1) { L = 1; R = 1; return; }               
        if (seed == 2) { L = N; R = N; return; }               
        if (seed == 3) { L = 32; R = 33; return; }             
        int t = rnd.next(0, 9);
        if (t == 0) { L = 1; R = N; return; }                  
        if (t == 1) { 
            long long mid = max(1LL, N / 2);
            long long width = min(N, 1000LL);
            L = max(1LL, mid - width);
            R = min(N, mid + width);
            return;
        }
        if (t == 2) { 
            L = 1;
            R = min(N, 70LL);
            return;
        }
        if (t == 3) { 
            L = min(N, 65LL);
            R = min(N, 5000LL);
            return;
        }
        if (t == 4) { 
            long long width = min(N, 100000LL);
            L = max(1LL, N - width);
            R = N;
            return;
        }
        if (t == 5) { 
            long long s = (long long) sqrt((long double)N);
            long long width = max(1LL, s / 10);
            L = max(1LL, s - width);
            R = min(N, s + width);
            return;
        }
        if (t == 6) { 
            long long p = 1;
            while ((p << 1) <= N && p <= (LLONG_MAX / 2)) p <<= 1;
            long long width = min(N, 2048LL);
            L = max(1LL, p - width);
            R = min(N, p + width);
            return;
        }
        if (t == 7) { 
            long long width = rnd.next(1LL, min(N, 1'000'000LL));
            long long center = rnd.next(1LL, N);
            L = max(1LL, center - width);
            R = min(N, center + width);
            if (L > R) swap(L, R);
            return;
        }
        
        L = 1;
        R = N;
    };

    
    int seed = 1;
    if (argc >= 2) {
        
        
        seed = atoi(argv[1]);
        if (seed <= 0) seed = 1;
    }

    
    
    (void)T;

    long long N = pickN(seed);

    if (mode == "non") {
        long long C = pickC_non(N, seed);
        
        cout << 1 << "\n";
        cout << N << " " << C << "\n";
        return 0;
    } else if (mode == "adp") {
        long long L, R;
        pickParams_adp(N, seed, L, R);
        
        
        cout << 1 << "\n";
        cout << N << " " << L << " " << R << "\n";
        return 0;
    } else {
        
        long long C = pickC_non(N, seed);
        cout << 1 << "\n";
        cout << N << " " << C << "\n";
        return 0;
    }
}