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

#include <bits/stdc++.h>
using namespace std;
#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")
#pragma GCC optimization("unroll-loops")
long long fastpow(long long base, long long power, long long M) {
  if (power == 1) return base;
  long long val = fastpow(base, power / 2, M);
  return (power % 2 == 0) ? (val * val) % M : (((val * val) % M) * base) % M;
}
inline void debugMode() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
}
const int N = 1e5 + 1;
const int MOD = 1e9 + 7;
int dx[] = {1, -1, 0, 0};
int dy[] = {0, 0, 1, -1};
vector<int> v[N], o, e, vis(N);
set<pair<int, int>> st;
int main() {
  debugMode();
  int n;
  cin >> n;
  cout << "? 1" << endl;
  for (int i = 1; i <= n; i++) {
    int x;
    cin >> x;
    if (x == 1) v[1].push_back(i);
    if (x == 0) continue;
    if (x & 2)
      o.push_back(i);
    else
      e.push_back(i);
  }
  vis[1] = true;
  int arr[n + 1];
  if (o <= e) {
    for (int i = 0; i < o.size(); i++) {
      cout << "? " << o[i] << endl << flush;
      for (int j = 1; j <= n; j++) {
        cin >> arr[j];
        if (arr[j] == 1) st.insert({min(j, o[i]), max(j, o[i])});
      }
    }
  } else {
    for (int i = 0; i < e.size(); i++) {
      cout << "? " << e[i] << endl << flush;
      for (int j = 1; j <= n; j++) {
        cin >> arr[j];
        if (arr[j] == 1) st.insert({min(j, e[i]), max(j, e[i])});
      }
    }
  }
  cout << '!' << endl;
  for (auto it = st.begin(); it != st.end(); it++)
    cout << it->first << " " << it->second << endl;
  return 0;
}
