Problem: cf1729_e
Difficulty: easy
Categories: graph, math
Time limit: 1000 ms, memory limit: 256 MB

This is an interactive problem.

I want to play a game with you...

We hid from you a cyclic graph of $n$ vertices ($3 \le n \le 10^{18}$). A cyclic graph is an undirected graph of $n$ vertices that form one cycle. Each vertex belongs to the cycle, i.e. the length of the cycle (the number of edges in it) is exactly $n$. The order of the vertices in the cycle is arbitrary.

You can make queries in the following way:

* "? a b" where $1 \le a, b \le 10^{18}$ and $a \neq b$. In response to the query, the interactor outputs on a separate line the length of random of two paths from vertex $a$ to vertex $b$, or -1 if $\max(a, b) > n$. The interactor chooses one of the two paths with equal probability. The length of the path —is the number of edges in it.

You win if you guess the number of vertices in the hidden graph (number $n$) by making no more than $50$ queries.

Note that the interactor is implemented in such a way that for any ordered pair $(a, b)$, it always returns the same value for query "? a b", no matter how many such queries. Note that the "? b a" query may be answered differently by the interactor.

The vertices in the graph are randomly placed, and their positions are fixed in advance.

The number of tests the jury has is $50$.

Interaction

You can make no more than $50$ of queries. To make a query, output on a separate line:

* "? a b", where $1 \le a, b \le 10^{18}$ and $a \neq b$. In response to the query, the interactor will output on a separate line the length of a random simple path from vertex $a$ to vertex $b$ (not to be confused with the path from $b$ to $a$), or $-1$ if $\max(a, b) > n$. The interactor chooses one of the two paths with equal probability.

If your program gets a number 0 as a result of a query, it means that the verdict for your solution is already defined as "wrong answer" (for example, you made more than $50$ queries or made an invalid query). In this case, your program should terminate immediately. Otherwise, in this scenario you may get a random verdict "Execution error", "Exceeded time limit" or some other verdict instead of "Wrong answer".

The answer, like queries, print on a separate line. The output of the answer is not counted as a query when counting them. To print it, use the following format:

* "! n": the expected size of the hidden graph ($3 \le n \le 10^{18}$).

After that, your program should terminate.

After the output of the next query, be sure to use stream cleaning functions so that some of your output is not left in some buffer. For example, in C++ you should use function flush(stdout), in Java call System.out.flush(), in Pascal flush(output) and stdout.flush() for Python.

Note that the interactor is implemented in such a way that for any ordered pair $(a, b)$, it always returns the same value for query "? a b", no matter how many such queries. Note that the "? b a" query may be answered differently by the interactor.

The vertices in the graph are randomly placed, and their positions are fixed in advance.

The number of tests the jury has is $50$.

Example

Input

```
1

2

-1
```

Output

```
? 1 2

? 1 3

? 1 4

! 3
```

Note

In the first example, the graph could look like this

 ![](https://espresso.codeforces.com/94c82fcd7a0af9554e6c69e31c1be68aa1811b72.png) 

The lengths of the simple paths between all pairs of vertices in this case are $1$ or $2$.

* The first query finds out that one of the simple paths from vertex $1$ to vertex $2$ has a length of $1$.
* With the second query, we find out that one of the simple paths from vertex $1$ to vertex $3$ has length $2$.
* In the third query, we find out that vertex $4$ is not in the graph. Consequently, the size of the graph is $3$.

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


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


static const long long HARD_CAP = 2000;


static long long hidden_n = -1;
static long long seed_val = 0;



static vector<int> small_perm;
static bool use_small_perm = false;


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 uint64_t splitmix64(uint64_t x) {
    x += 0x9e3779b97f4a7c15;
    x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
    x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
    return x ^ (x >> 31);
}


static long long get_pos(long long u) {
    if (use_small_perm) {
        
        
        if (u < 1 || u > hidden_n) return 0; 
        return small_perm[u - 1];
    } else {
        
        uint64_t h = splitmix64((uint64_t)u ^ (uint64_t)seed_val);
        return h % hidden_n;
    }
}



static int get_path_choice(long long u, long long v) {
    
    uint64_t h = splitmix64((uint64_t)u + 0x9e3779b97f4a7c15 + ((uint64_t)v << 6) + ((uint64_t)v >> 2));
    
    h = splitmix64(h ^ (uint64_t)seed_val);
    return h % 2;
}

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

    
    
    string mode = inf.readToken();
    if (mode == "FIXED") {
        hidden_n = inf.readLong();
        seed_val = inf.readLong();
    } else if (mode == "ADAPTIVE") {
        long long min_n = inf.readLong();
        long long max_n = inf.readLong();
        seed_val = inf.readLong();
        
        mt19937_64 rng(seed_val);
        hidden_n = min_n + (rng() % (max_n - min_n + 1));
    } else {
        finish(_fail, "Unknown generator mode: " + mode);
    }

    
    if (hidden_n <= 1000000) {
        
        use_small_perm = true;
        small_perm.resize(hidden_n);
        iota(small_perm.begin(), small_perm.end(), 0);
        mt19937_64 rng(seed_val);
        shuffle(small_perm.begin(), small_perm.end(), rng);
    } else {
        
        use_small_perm = false;
    }

    
    log_metrics();

    
    while (true) {
        
        if (queries >= HARD_CAP) {
            finish(_pe, "Hard query limit exceeded (" + to_string(HARD_CAP) + ")");
        }

        string token;
        if (!(cin >> token)) {
            finish(_pe, "Unexpected EOF (expected '?' or '!')");
        }

        if (token == "!") {
            
            long long ans;
            if (!(cin >> ans)) finish(_pe, "Expected number after '!'");
            
            if (ans == hidden_n) {
                finish(_ok, "Guessed correct n=" + to_string(hidden_n));
            } else {
                finish(_wa, "Guessed n=" + to_string(ans) + ", expected n=" + to_string(hidden_n));
            }
        } else {
            
            long long a, b;
            
            if (token == "?") {
                if (!(cin >> a >> b)) finish(_pe, "Expected two numbers after '?'");
            } else {
                try {
                    a = stoll(token);
                } catch (...) {
                    finish(_pe, "Invalid token '" + token + "' (expected '?' or number)");
                }
                if (!(cin >> b)) finish(_pe, "Expected second number for query");
            }

            
            queries++;
            
            if (queries % 10 == 0) log_metrics();

            
            if (a < 1 || b < 1 || a > 1000000000000000000LL || b > 1000000000000000000LL) {
                finish(_wa, "Query parameters out of bounds [1, 10^18]");
            }
            if (a == b) {
                finish(_wa, "Invalid query: a == b");
            }

            
            long long response = -1;
            if (a > hidden_n || b > hidden_n) {
                response = -1;
            } else {
                long long pa = get_pos(a);
                long long pb = get_pos(b);
                long long dist = abs(pa - pb);
                
                long long paths[2] = {dist, hidden_n - dist};
                
                
                int choice = get_path_choice(a, b);
                response = paths[choice];
            }

            cout << response << endl;
        }
    }

    return 0;
}


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




static long long queries = 0;
static const long long query_limit = 50;  
static const long long hard_cap = 500;    


static long long hidden_n = 0;
static long long seed_val = 0;




static const long long SMALL_N_THRESHOLD = 200000;
static vector<long long> small_perm;
static map<long long, long long> large_pos;
static set<long long> used_vals;


static map<pair<long long, long long>, long long> memo_ans;




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());
}




long long get_position(long long u) {
    
    if (u < 1 || u > hidden_n) return -1; 

    if (hidden_n <= SMALL_N_THRESHOLD) {
        return small_perm[u - 1];
    } else {
        if (large_pos.count(u)) {
            return large_pos[u];
        }
        
        
        
        
        long long p;
        int tries = 0;
        do {
            p = rnd.next(0LL, hidden_n - 1);
            tries++;
            if (tries > 1000) {
                
                break; 
            }
        } while (used_vals.count(p));
        
        used_vals.insert(p);
        large_pos[u] = p;
        return p;
    }
}




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

    
    
    string mode = inf.readToken();
    if (mode == "ADAPTIVE") {
        long long min_n = inf.readLong();
        long long max_n = inf.readLong();
        seed_val = inf.readLong();
        
        
        rnd.setSeed(seed_val);
        hidden_n = rnd.next(min_n, max_n);
    } else {
        
        hidden_n = inf.readLong();
        seed_val = inf.readLong();
        
        
        rnd.setSeed(seed_val);
    }

    
    if (hidden_n <= SMALL_N_THRESHOLD) {
        small_perm.resize(hidden_n);
        iota(small_perm.begin(), small_perm.end(), 0);
        shuffle(small_perm.begin(), small_perm.end());
    }

    
    
    
    
    log_metrics();

    
    while (true) {
        string token;
        
        if (!(cin >> token)) {
            
            finish(_pe, "Unexpected EOF (did not receive answer)");
        }

        if (token == "!") {
            
            long long guess;
            if (!(cin >> guess)) {
                finish(_pe, "Expected integer after '!'");
            }

            if (guess == hidden_n) {
                finish(_ok, format("Correct! n=%lld", hidden_n));
            } else {
                finish(_wa, format("Wrong answer. Expected %lld, got %lld", hidden_n, guess));
            }

        } else if (token == "?") {
            
            queries++;
            if (queries > hard_cap) {
                finish(_pe, "Hard query limit exceeded (potential infinite loop)");
            }
            
            if (queries % 10 == 0) log_metrics();

            long long a, b;
            if (!(cin >> a >> b)) {
                finish(_pe, "Expected two integers after '?'");
            }

            
            if (a < 1 || a > 1000000000000000000LL || b < 1 || b > 1000000000000000000LL) {
                finish(_pe, "Query arguments out of bounds [1, 10^18]");
            }
            if (a == b) {
                finish(_pe, "Query arguments must be distinct");
            }

            
            long long ans = -1;
            if (a > hidden_n || b > hidden_n) {
                ans = -1;
            } else {
                
                if (memo_ans.count({a, b})) {
                    ans = memo_ans[{a, b}];
                } else {
                    
                    long long p_a = get_position(a);
                    long long p_b = get_position(b);
                    long long dist = abs(p_a - p_b);
                    
                    
                    long long path1 = dist;
                    long long path2 = hidden_n - dist;
                    
                    
                    if (rnd.next(0, 1) == 0) {
                        ans = path1;
                    } else {
                        ans = path2;
                    }
                    
                    memo_ans[{a, b}] = ans;
                }
            }

            
            cout << ans << endl;

        } else {
            finish(_pe, format("Invalid token '%s'", token.c_str()));
        }
    }

    return 0;
}


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 interactor_seed = rnd.next(1LL, 2000000000000000000LL);

    if (mode == "adp") {
        
        
        cout << "ADAPTIVE 3 1000000000000000000 " << interactor_seed << endl;
    } else {
        
        long long n = -1;

        
        
        long long s_idx = -1;
        try {
            string s = argv[1];
            if (!s.empty() && all_of(s.begin(), s.end(), ::isdigit)) {
                s_idx = stoll(s);
            }
        } catch (...) {}

        if (s_idx >= 1 && s_idx <= 20) {
            
            vector<long long> manual_cases = {
                3, 4, 5,                         
                49, 50, 51,                      
                100, 1000, 1000000007,           
                (1LL << 16), (1LL << 32), (1LL << 59), 
                1000000000000000000LL,           
                999999999999999999LL,            
                999999999999999997LL,            
                123456789012345678LL,            
                500000000000000000LL,            
                (1LL << 60) - 1,                 
                900000000000000000LL,            
                (1LL << 50) + 7                  
            };
            if (s_idx - 1 < (long long)manual_cases.size()) {
                n = manual_cases[s_idx - 1];
            }
        }

        
        if (n == -1) {
            int type = rnd.next(1, 100);
            if (type <= 10) {
                
                n = rnd.next(3LL, 1000LL);
            } else if (type <= 40) {
                
                int p = rnd.next(2, 59);
                long long base = (1LL << p);
                n = base + rnd.next(-100, 100);
            } else if (type <= 70) {
                
                n = rnd.next(900000000000000000LL, 1000000000000000000LL);
            } else {
                
                n = rnd.next(3LL, 1000000000000000000LL);
            }
        }

        
        if (n < 3) n = 3;
        if (n > 1000000000000000000LL) n = 1000000000000000000LL;

        cout << "FIXED " << n << " " << interactor_seed << endl;
    }

    return 0;
}