//prewritten code: https://github.com/antma/algo
import std.algorithm;
import std.array;
import std.conv;
import std.math;
import std.range;
import std.stdio;
import std.string;
import std.traits;
import std.exception;

T gcd(T) (T a, T b) pure nothrow @nogc {
  if (a < b) {
    swap (a, b);
  }
  while (b) {
    T c = a % b; a = b; b = c;
  }
  return a;
}

T gcdext(T) (T a, T b, ref T x, ref T y) pure nothrow @nogc {
  if (b == 0) {
    x = 1;
    y = 0;
    return a;
  }
  T res = gcdext (b, a % b, y, x);
  y -= x * (a / b);
  return res;
}

struct IntM {
  enum q = 1_000_003;
  int v;
  this (int m) pure nothrow @nogc {
    v = m % q;
    if (v < 0) {
      v += q;
    }
  }
  IntM opAssign (int m) pure nothrow @nogc {
    v = m % q;
    if (v < 0) {
      v += q;
    }
    return this;
  }
  IntM opUnary (string op : "-")() const pure nothrow @nogc {
    return IntM ((q - v) % q);
  }
  ref IntM opUnary (string op : "++")() pure nothrow @nogc {
    if (++v >= q) {
      v -= q;
    }
    return this;
  }
  ref IntM opUnary (string op : "--")() pure nothrow @nogc {
    if (--v < 0) {
      v += q;
    }
    return this;
  }
  ref IntM opOpAssign (string op : "+")(in IntM rhs) pure nothrow @nogc {
    v += rhs.v;
    v %= q;
    return this;
  }
  ref IntM opOpAssign (string op : "-")(in IntM rhs) pure nothrow @nogc {
    v -= rhs.v;
    v %= q;
    return this;
  }
  ref IntM opOpAssign (string op : "*")(in IntM rhs) pure nothrow @nogc {
    v = ((v.to!(long)) * rhs.v.to!(long)) % q;
    return this;
  }
  IntM opBinary (string op : "+")(in IntM rhs) const pure nothrow @nogc {
    return IntM ( (v + rhs.v) % q);
  }
  IntM opBinary (string op : "-")(in IntM rhs) const pure nothrow @nogc {
    return IntM ( (v - rhs.v) % q);
  }
  IntM opBinary (string op : "*")(in IntM rhs) const pure nothrow @nogc {
    return IntM (((v.to!(long)) * rhs.v.to!(long)) % q);
  }
  IntM opBinary (string op : "^^")(in int rhs) const pure nothrow @nogc {
    IntM a = 1, b = this;
    int p = rhs;
    while (p > 0) {
      //a * (b ^ p) == x ^ rhs
      if (p & 1) {
        a *= b;
      }
      b *= b;
      p >>>= 1;
    }
    return a;
  }
  IntM opBinary (string op)(in int v) const pure nothrow @nogc if (op == "+" || op == "-" || op == "*") {
    mixin ("return this " ~ op ~ " IntM(v);");
  }
  int opCast(T : int)() const pure nothrow @nogc { return v; }
  int opCmp (const IntM rhs) const pure nothrow @nogc {
    if (v < rhs.v) {
      return -1;
    }
    if (v > rhs.v) {
      return 1;
    }
    return 0;
  }
  bool opEquals (const IntM rhs) const pure nothrow @nogc { return v == rhs.v; }
  string toString() const pure nothrow { return ((v < 0) ? v + q : v).text; }
}

void main() {
  IntM[][] a = new IntM[][] (11, 11);
  IntM[11] b;
  foreach (i; 0 .. 11) {
    IntM ii = i;
    writeln ("? ", i); stdout.flush ();
    a[i][0] = 1;
    foreach (j; 1 .. 11) {
      a[i][j] = a[i][j-1] * ii;
    }
    int bi = readln.strip.to!int;
    b[i] = bi;
  }
  immutable IntM z = 0;
  foreach (i; 0 .. 11) {
    enforce (a[i][i] != z);
    foreach (j; i + 1 .. 11) {
      IntM aji = a[j][i];
      foreach (k; i .. 11) {
        a[j][k] *= a[i][i];
        a[j][k] -= a[i][k] * aji;
      }
      b[j] *= a[i][i];
      b[j] -= b[i] * aji;
    }
  }
  IntM[11] x;
  foreach_reverse (i; 0 .. 11) {
    x[i] = b[i];
    foreach (j; i + 1 .. 11) {
      x[i] -= a[i][j] * x[j];
    }
    x[i] *= a[i][i] ^^ (IntM.q - 2);
  }
  debug stderr.writeln (a);
  debug stderr.writeln (b);
  debug stderr.writeln (x);
  foreach (i; 0 .. IntM.q) {
    IntM r;
    IntM ii = i;
    foreach_reverse (j; 0 .. 11) {
      r *= ii;
      r += x[j];
    }
    if (r == z) {
      writeln ("! ", i);
      return;
    }
  }
  writeln ("! ", -1);
}

