5
5 3
2 4
3 1
4 5
 4
2 4
3 2
2 1
 5
5 3
2 4
3 1
4 5
 2
1 2
 4
3 4
2 3
3 1
 10
8 10
2 9
7 8
4 1
7 3
4 7
2 5
2 4
4 6
 5
3 4
3 2
3 1
1 5
 3
1 2
2 3
 5
1 2
1 3
1 4
1 5

1 2
2 3
2 4
 1 3
2 4
3 5
4 5
 1 2
 1 3
2 3
3 4
 1 4
2 4
2 5
2 9
3 7
4 6
4 7
7 8
8 10
 1 3
1 5
2 3
3 4
 1 2
2 3
 1 2
1 3
1 4
1 5

#pragma GCC optimize("Ofast,unroll-loops,fast-math")

#ifdef ME_LOCAL
	#pragma GCC target("sse4")
#else
	#pragma GCC target("avx,avx2,sse4,fma")
#endif // ME_LOCAL


#include <bits/stdc++.h>
using namespace std;

using ll = int64_t;
using ull = uint64_t;
using i128 = __int128_t;
using u128 = __uint128_t;

using db = double;
using ld = long double;

using vi = vector<int>;
using vb = vector<bool>;

using pii = pair<int, int>;
using vpi = vector<pii>;

using pll = pair<ll, ll>;
using vpl = vector<pll>;

using rng = default_random_engine;


template <typename T>
using minpq = priority_queue<T, vector<T>, greater<T>>;


/* =-- order statistics tree and gp_hash_table --= */

// #include <ext/pb_ds/assoc_container.hpp>
// using namespace __gnu_pbds;
// template <class T> using Tree = tree<T, null_type, less<T>,
// 	rb_tree_tag, tree_order_statistics_node_update>;


template<class F>
class y_combinator_result {
	F f_;
public:
	template<class T> explicit y_combinator_result(T &&f): f_(forward<T>(f)) {}
	template<class ...Args> decltype(auto) operator()(Args &&...args) {
		return f_(ref(*this), forward<Args>(args)...);
	}
};

template<class F> decltype(auto) y_combinator(F &&f) {
	return y_combinator_result<decay_t<F>>(forward<F>(f));
}


template <typename T, typename U>
inline bool ckmin(T &x, const U &y) {
	return x>y ? x=y,1 : 0; }

template <typename T, typename U>
inline bool ckmax(T &x, const U &y) {
	return x<y ? x=y,1 : 0; }


#define F first
#define S second
#define lb lower_bound
#define ub upper_bound
#define np next_permutation
#define sz(v) int(v.size())
#define all(v) begin(v), end(v)

#define loop while (9+10 != 21)

#define ctz __builtin_ctzll // count trailing zeros
#define clz __builtin_clzll // count leading zeros
#define bitpar __builtin_parityll // parity of number of set bits
#define popcnt __builtin_popcountll // number of set bits

constexpr int dx[4] = {0, 1, 0, -1};
constexpr int dy[4] = {1, 0, -1, 0};

constexpr int INF = 200000'3435;
constexpr ll INFL = 900000'3435e9;
constexpr int M1 = 1'000'000'007;
constexpr int M2 =   998'244'353;
constexpr int maxn = 400'005;
constexpr int maxg = 2'005;

/* ---------- end template ---------- */

int d[maxn], n;
bool vis[maxn];
vector<int> adj[maxn];

void dfs(int c, int p) {
}

void solve() {
	cin >> n;
	
	fill_n(d, n, 0);
	fill_n(vis, n, false);
	for (int i = 0; i < n; ++i)
		adj[i].clear();
	
	cout << "? 1" << endl;
	for (int i = 0; i < n; ++i) {
		cin >> d[i];
		// if (d[i] == 1)
		// 	adj[0].push_back(i);
	}
	
	for (int i = 0; i < n; ++i) {
		if (~d[i]&1) continue;
		cout << "? " << i+1 << '\n';
		for (int d, j = 0; j < n; ++j) {
			cin >> d; if (d == 1) adj[i].push_back(j);
		}
	}
	
	cout << "!\n";
	for (int i = 0; i < n; ++i)
		for (const int &j: adj[i])
			cout << i+1 << ' ' << j+1 << '\n';
}



int main() {
	// cin.tie(nullptr) ->
	// sync_with_stdio(false);
	cin.exceptions(cin.failbit);
	cout << fixed << setprecision(12);

	int T = 1; // cin >> T;
	while (T--) solve();
}