#pragma GCC optimize("O2") #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define int ll #define INT128_MAX (__int128)(((unsigned __int128) 1 << ((sizeof(__int128) * __CHAR_BIT__) - 1)) - 1) #define INT128_MIN (-INT128_MAX - 1) #define clock chrono::steady_clock::now().time_since_epoch().count() #ifdef DEBUG #define dbg(x) cout << (#x) << " = " << x << '\n' #else #define dbg(x) #endif namespace R = std::ranges; namespace V = std::views; using namespace std; using ll = long long; using ull = unsigned long long; using ldb = long double; using pii = pair; using pll = pair; //#define double ldb template ostream& operator<<(ostream& os, const pair pr) { return os << pr.first << ' ' << pr.second; } template ostream& operator<<(ostream& os, const array &arr) { for(const T &X : arr) os << X << ' '; return os; } template ostream& operator<<(ostream& os, const vector &vec) { for(const T &X : vec) os << X << ' '; return os; } template ostream& operator<<(ostream& os, const set &s) { for(const T &x : s) os << x << ' '; return os; } int query(int i, int j) { cout << "? " << i + 1 << ' ' << j + 1 << '\n'; int x; cin >> x; return x; } void answer(vector a, vector b) { cout << "! " << a << ' ' << b << '\n'; } bool prime[1001]; signed main() { //ios::sync_with_stdio(false), cin.tie(NULL); fill(prime + 2, prime + 1001, true); for(int i = 4; i < 1001; i++) for(int j = 2; j < i; j++) if (i % j == 0) prime[i] = false; /* for(int n = 2; n <= 1000; n++) { bool ok = false; for(int i = (n + 1) / 2 + 1; i <= n; i++) ok = ok or prime[i]; if (!ok) cout << n << " not ok\n"; } */ int n; cin >> n; if (n == 1) { vector a(1, 1); answer(a, a); return 0; } int p = -1, ppos = -1; { int init = rand() % n; vector s(n); for(int i = 0; i < n; i++) s[i] = query(init, i); int mn = R::min(s); for(int i = 0; i < n; i++) if (prime[s[i] / mn] and s[i] / mn >= (n + 1) / 2 + 1) p = s[i] / mn, ppos = i; if (p == -1) p = mn, ppos = init; } vector a(n, -1), b(n, -1); array cand = {-1, -1}; { vector s(n); for(int i = 0; i < n; i++) s[i] = query(i, ppos); for(int i = 0; i < n; i++) { if (s[i] == p) cand[cand[0] != -1] = i; else a[i] = s[i] / p; } } { vector s(n); for(int i = 0; i < n; i++) s[i] = query(cand[0], i); int mn = R::min(s); if (mn == 1) { a[cand[0]] = 1, a[cand[1]] = p; b = s; } else { a[cand[0]] = p, a[cand[1]] = 1; for(int i = 0; i < n; i++) { if (s[i] == p) b[i] = (i == ppos ? p : 1); else b[i] = s[i] / p; } } } answer(a, b); return 0; }