Problem: cf1155_e
Difficulty: medium
Categories: math
Time limit: 2000 ms, memory limit: 256 MB

Jury picked a polynomial $f(x) = a_0 + a_1 \cdot x + a_2 \cdot x^2 + \dots + a_k \cdot x^k$. $k \le 10$ and all $a_i$ are integer numbers and $0 \le a_i < 10^6 + 3$. It's guaranteed that there is at least one $i$ such that $a_i > 0$.

Now jury wants you to find such an integer $x_0$ that $f(x_0) \equiv 0 \mod (10^6 + 3)$ or report that there is not such $x_0$.

You can ask no more than $50$ queries: you ask value $x_q$ and jury tells you value $f(x_q) \mod (10^6 + 3)$.

Note that printing the answer doesn't count as a query.

Interaction

To ask a question, print "? $x_q$" $(0 \le x_q < 10^6 + 3)$. The judge will respond with a single integer $f(x_q) \mod (10^6 + 3)$. If you ever get a result of $−1$ (because you printed an invalid query), exit immediately to avoid getting other verdicts.

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.

When you are ready to answer, print "! $x_0$" where $x_0$ is the answer or $-1$ if there is no such $x_0$.

You can ask at most $50$ questions per test case.

Examples

Input

```
1000002

0
```

Output

```
? 0

? 1

! 1
```

Input

```
5

2

1
```

Output

```
? 2

? 1

? 0

! -1
```

Note

The polynomial in the first sample is $1000002 + x^2$.

The polynomial in the second sample is $1 + x^2$.

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


static const int MOD = 1000003;
static int k;
static vector<int> a;


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


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


template<typename... Args>
static void finish(TResult verdict, const char* fmt, Args... args) {
    log_metrics();
    quitf(verdict, fmt, args...);
}


long long eval_poly(int x) {
    long long res = 0;
    for (int i = k; i >= 0; --i) {
        res = (res * x + a[i]) % MOD;
    }
    return res;
}

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

    
    
    k = inf.readInt();
    a.resize(k + 1);
    for (int i = 0; i <= k; ++i) {
        a[i] = inf.readInt();
    }
    
    
    
    bool exists_root = false;
    for (int x = 0; x < MOD; ++x) {
        if (eval_poly(x) == 0) {
            exists_root = true;
            break;
        }
    }

    
    log_metrics();

    
    
    int hard_cap = 2000; 

    while (true) {
        
        if (queries > hard_cap) {
            finish(_pe, "Hard query limit exceeded (infinite loop protection)");
        }

        string token;
        
        if (!(cin >> token)) {
            finish(_pe, "Unexpected end of output");
        }

        if (token == "?") {
            
            string x_str;
            if (!(cin >> x_str)) finish(_pe, "Unexpected EOF after '?'");
            
            long long x;
            try {
                size_t idx;
                x = stoll(x_str, &idx);
                if (idx != x_str.size()) throw invalid_argument("");
            } catch (...) {
                finish(_pe, "Invalid integer format for query");
            }
            
            
            if (x < 0 || x >= MOD) {
                
                cout << -1 << endl;
                finish(_pe, "Query x=%lld out of range [0, %d)", x, MOD);
            }

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

            long long val = eval_poly((int)x);
            cout << val << endl;
        } 
        else if (token == "!") {
            
            string ans_str;
            if (!(cin >> ans_str)) finish(_pe, "Unexpected EOF after '!'");
            
            long long ans;
            try {
                size_t idx;
                ans = stoll(ans_str, &idx);
                if (idx != ans_str.size()) throw invalid_argument("");
            } catch (...) {
                finish(_pe, "Invalid integer format for answer");
            }
            
            if (ans == -1) {
                if (exists_root) {
                    finish(_wa, "Reported -1 but a root exists");
                } else {
                    finish(_ok, "Correct: no root exists");
                }
            } else {
                if (ans < 0 || ans >= MOD) {
                    finish(_wa, "Answer %lld out of range [0, %d)", ans, MOD);
                }
                if (eval_poly((int)ans) == 0) {
                    finish(_ok, "Correct root found: %lld", ans);
                } else {
                    finish(_wa, "Value %lld is not a root (f(x) != 0)", ans);
                }
            }
        } 
        else {
            
            long long x;
            bool is_valid_num = true;
            try {
                size_t idx;
                x = stoll(token, &idx);
                if (idx != token.size()) is_valid_num = false;
            } catch (...) {
                is_valid_num = false;
            }

            if (is_valid_num) {
                
                if (x < 0 || x >= MOD) {
                    cout << -1 << endl;
                    finish(_pe, "Query x=%lld out of range [0, %d)", x, MOD);
                }
                queries++;
                if (queries % 10 == 0) log_metrics();
                long long val = eval_poly((int)x);
                cout << val << endl;
            } else {
                finish(_pe, "Invalid token '%s'", token.c_str());
            }
        }
    }

    return 0;
}


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

using namespace std;


const int MOD = 1000003;
const int QUERY_LIMIT_VAL = 50;


long long queries = 0;
long long query_limit = QUERY_LIMIT_VAL;


vector<int> poly;





void log_metrics() {
    try {
        tout << "queries=" << queries << endl;
        tout << "query_limit=" << query_limit << endl;
    } catch (...) {
        
    }
}





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




long long eval_poly(const vector<int>& a, long long x) {
    long long res = 0;
    
    x %= MOD;
    if (x < 0) x += MOD;
    
    for (int i = (int)a.size() - 1; i >= 0; --i) {
        res = (res * x + a[i]) % MOD;
    }
    return res;
}




bool has_root(const vector<int>& a) {
    for (int x = 0; x < MOD; ++x) {
        if (eval_poly(a, x) == 0) return true;
    }
    return false;
}

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

    
    int k = inf.readInt();
    
    
    
    inf.skipBlanks();
    if (!inf.eof()) {
        
        for (int i = 0; i <= k; ++i) {
            poly.push_back(inf.readInt());
        }
    } else {
        
        
        while (true) {
            poly.assign(k + 1, 0);
            bool all_zero = true;
            for (int i = 0; i <= k; ++i) {
                poly[i] = rnd.next(MOD);
                if (poly[i] > 0) all_zero = false;
            }
            if (!all_zero) break;
        }
    }

    
    log_metrics();

    
    
    while (true) {
        string type;
        
        if (!(cin >> type)) {
            
            finish(_pe, "Unexpected EOF reading query type");
        }

        if (type == "?") {
            long long x;
            if (!(cin >> x)) finish(_pe, "Expected integer after '?'");
            
            
            if (x < 0 || x >= MOD) {
                cout << -1 << endl; 
                finish(_pe, format("Query x=%lld out of range [0, %d)", x, MOD));
            }

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

            
            if (queries > 200) {
                finish(_pe, "Hard query limit exceeded (>200)");
            }

            
            long long val = eval_poly(poly, x);
            cout << val << endl; 
            
        } else if (type == "!") {
            long long x;
            if (!(cin >> x)) finish(_pe, "Expected integer after '!'");
            
            if (x == -1) {
                
                if (has_root(poly)) {
                    finish(_wa, "Contestant claims no root, but a root exists");
                } else {
                    finish(_ok, "Correct (no root)");
                }
            } else {
                
                long long val = eval_poly(poly, x);
                if (val == 0) {
                    finish(_ok, "Correct (root found)");
                } else {
                    finish(_wa, format("Output %lld is not a root (f(x) = %lld)", x, val));
                }
            }
            
            break;
        } else {
            finish(_pe, "Invalid query type: \"" + type + "\"");
        }
    }

    return 0;
}


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

using namespace std;

const int MOD = 1000003;


long long eval_poly(const vector<int>& a, int x) {
    long long res = 0;
    for (int i = (int)a.size() - 1; i >= 0; --i) {
        res = (res * x + a[i]) % MOD;
    }
    return res;
}


bool has_root(const vector<int>& a) {
    for (int x = 0; x < MOD; ++x) {
        if (eval_poly(a, x) == 0) return true;
    }
    return false;
}

int main(int argc, char* argv[]) {
    registerGen(argc, argv, 1);
    
    
    string mode = opt<string>("mode", "non");
    int k_arg = opt<int>("k", -1);
    
    
    int k;
    if (k_arg != -1) {
        k = k_arg;
    } else {
        
        int r = rnd.next(100);
        if (r < 5) k = 0;
        else if (r < 20) k = rnd.next(1, 5);
        else k = rnd.next(6, 10);
    }

    
    int type = rnd.next(3);
    
    
    long long seed = atoll(argv[1]);
    if (seed == 1) { k = 10; type = 1; }      
    else if (seed == 2) { k = 10; type = 2; } 
    else if (seed == 3) { k = 0; type = 2; }  
    else if (seed == 4) { k = 1; type = 1; }  
    else if (seed == 5) { k = 5; type = 0; }  
    
    
    if (k == 0) type = 2;

    
    if (mode == "adp") {
        cout << k << endl;
        return 0;
    }

    
    vector<int> a(k + 1);
    int retry_count = 0;
    const int MAX_RETRIES = 10; 
    while (true) {
        
        for (int i = 0; i <= k; ++i) {
            a[i] = rnd.next(MOD);
        }
        
        
        bool all_zero = true;
        for (int x : a) if (x > 0) all_zero = false;
        if (all_zero) {
            
            a[rnd.next(k + 1)] = rnd.next(1, MOD - 1);
        }

        if (type == 1) {
            
            int x0 = rnd.next(MOD);
            
            
            
            long long val = 0;
            long long p = x0;
            for (int i = 1; i <= k; ++i) {
                val = (val + (long long)a[i] * p) % MOD;
                p = (p * x0) % MOD;
            }
            
            
            a[0] = (MOD - val) % MOD;
            
            
            bool az = true;
            for (int x : a) if (x > 0) az = false;
            if (az) continue; 
            
            
            break;
            
        } else if (type == 2) {
            
            
            
            
            retry_count++;
            if (retry_count > MAX_RETRIES || !has_root(a)) break;
        } else {
            
            break;
        }
    }
    
    
    cout << k << endl;
    for (int i = 0; i <= k; ++i) {
        cout << a[i] << (i == k ? "" : " ");
    }
    cout << endl;
    
    return 0;
}