#include using namespace std; typedef long long ll; typedef long double ld; template bool chmax(T &a, const T &b) { if (a < b) { a = b; return 1; } return 0; } template bool chmin(T &a, const T &b) { if (b < a) { a = b; return 1; } return 0; } ll gcd(ll a, ll b) { if (a % b == 0) {return b;} else {return gcd(b, a % b);} } ll lcm(ll a, ll b) { return a / gcd(a, b) * b; } ll query(ll i, ll j) { cout << "?" << " " << i+1 << " " << j+1 << endl; ll X; cin >> X; return X; } void output(vector &A, vector &B) { assert(A.size() == B.size()); cout << "!" << " "; for (auto a : A) cout << a << " "; for (auto b : B) cout << b << " "; cout << endl; return; } mt19937 engine(42); const ll nmax = 1010; bool isprime[nmax]; const ll INF = 1e18; void init() { for (int i = 2; i < nmax; ++i) { bool flg = true; for (int j = 2; j * j <= i; ++j) { if (i % j == 0) flg = false; } isprime[i] = flg; } return; } int main() { init(); ll N; cin >> N; if (N <= 2) { if (N == 1) { cout << "!" << " " << 1 << " " << 1 << endl; return 0; } else { ll q00 = query(0, 0); ll q01 = query(0, 1); ll q10 = query(1, 0); ll q11 = query(1, 1); vector A(N), B(N); { if (q00 == q01) A[0] = 2; else A[0] = 1; A[1] = 3 - A[0]; } { if (q00 == q10) B[0] = 2; else B[0] = 1; B[1] = 3 - B[0]; } output(A, B); return 0; } return 0; } ll a0 = INF, p = -1; ll bp = -1; { ll f = engine() % N; vector b(N); for (int i = 0; i < N; ++i) b[i] = query(f, i); for (auto bb : b) chmin(a0, bb); for (int n = 1; n <= N; ++n) { if (isprime[n] && gcd(a0, n) == 1) p = n; } assert(p != -1); ll lc = lcm(a0, p); for (int i = 0; i < N; ++i) { if (b[i] == lc) bp = i; } } // cerr << p << endl; vector A(N), B(N); { vector veca(N); vector pid; for (int i = 0; i < N; ++i) { ll a = query(i, bp); veca[i] = a; for (int j = 1; j <= N; ++j) { if (lcm(j, p) == a) A[i] = j; } if (a == p) pid.emplace_back(i); } vector vecb(N); assert((ll)pid.size() == 2); ll ap0 = pid[0], ap1 = pid[1]; bool isone = false; for (int i = 0; i < N; ++i) { vecb[i] = query(ap0, i); if (vecb[i] == 1) isone = true; } if (isone) { A[ap0] = 1, A[ap1] = p; for (int i = 0; i < N; ++i) { B[i] = vecb[i]; } } else { A[ap0] = p, A[ap1] = 1; for (int i = 0; i < N; ++i) { ll b = vecb[i]; for (int j = 1; j <= N; ++j) { if (lcm(p, j) == b) B[i] = j; } if (b == p) { if (i == bp) B[i] = p; else B[i] = 1; } } } } vector copya = A, copyb = B; sort(copya.begin(), copya.end()); sort(copyb.begin(), copyb.end()); for (int i = 0; i < N; ++i) { // cout << i << " " << copya[i] << " " << copyb[i] << endl; assert(copya[i] == i+1); assert(copyb[i] == i+1); } output(A, B); return 0; }