#include <bits/stdc++.h>
using namespace std;
const int N = 1003, mod = 998244353;
template <typename T>
void read(T &x) {
  int ch = getchar();
  x = 0;
  bool f = false;
  for (; ch < '0' || ch > '9'; ch = getchar()) f |= ch == '-';
  for (; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
  if (f) x = -x;
}
int n, fa[N];
bool vis[N];
vector<int> in[N], nxt[N], pos;
char str[N];
map<vector<int>, vector<bool> > buc;
vector<bool> query(const vector<int> &v) {
  if (buc.count(v)) return buc[v];
  putchar('?');
  for (int u : v) printf(" %d", u);
  putchar('\n');
  fflush(stdout);
  scanf("%s", str);
  vector<bool> res(n);
  for (int i = 0; i < n; ++i) res[i] = (str[i] != '0');
  return buc[v] = res;
}
int main() {
  read(n);
  in[0].emplace_back(0);
  vis[0] = vis[n] = true;
  for (int i = 1; i < n; ++i) nxt[0].emplace_back(i);
  while (true) {
    bool flg = true;
    pos.resize(0);
    for (int i = 0; i <= n; ++i)
      if (vis[i]) pos.emplace_back(i);
    for (int _ = 0; _ < 2; ++_) {
      vector<int> d1(n, 0), d2(n, 0);
      for (int i = _; i + 1 < pos.size(); i += 2) {
        if (in[pos[i]].empty() || pos[i + 1] == pos[i] + 1) continue;
        if (pos[i + 1] == pos[i] + 2) {
          in[pos[i] + 1] = nxt[pos[i]];
          nxt[pos[i]].resize(0);
          vis[pos[i] + 1] = true;
          continue;
        }
        flg = false;
        int mid = pos[i] + pos[i + 1] + 1 >> 1;
        for (int u : in[pos[i]]) {
          d2[u] = mid - pos[i];
          d1[u] = d2[u] - 1;
        }
      }
      vector<bool> a1 = query(d1), a2 = query(d2);
      for (int i = _; i + 1 < pos.size(); i += 2) {
        if (in[pos[i]].empty() || pos[i + 1] <= pos[i] + 2) continue;
        int mid = pos[i] + pos[i + 1] + 1 >> 1;
        vector<int> tmp = nxt[pos[i]];
        nxt[pos[i]].resize(0);
        for (int x : tmp) {
          if (a1[x])
            nxt[pos[i]].emplace_back(x);
          else if (a2[x])
            in[mid].emplace_back(x);
          else
            nxt[mid].emplace_back(x);
        }
        vis[mid] = true;
      }
    }
    if (flg) break;
  }
  for (int _ = 1; _ <= 3; ++_)
    for (int i = 0; (1 << i) < n; ++i) {
      vector<int> d(n, 0);
      bool flg = true;
      for (int x = _; x < n; x += 3)
        if (!in[x].empty())
          for (int v : in[x - 1])
            if (v >> i & 1) {
              d[v] = 1;
              flg = false;
            }
      if (flg) continue;
      vector<bool> res = query(d);
      for (int x = _; x < n; x += 3)
        if (!in[x].empty())
          for (int v : in[x])
            if (res[v]) fa[v] |= 1 << i;
    }
  puts("!");
  for (int i = 1; i < n; ++i) printf("%d %d\n", fa[i] + 1, i + 1);
}
