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

const int N = 200;

int n, par[N], sz[N], q = 0, a = 0, b = 0;

int find(int v) {
	return par[v] == v ? v : (par[v] = find(par[v]));
}

bool merge(int u, int v) {
	u = find(u), v = find(v);
	if(u == v) return 0;

	par[v] = u;
	sz[u] += sz[v];
	return 1;
}

map<vector<int>, int> memo;

bool found(int p, int l, int x) {
	vector<int> ask(n + 1);
	ask[p] = 1;
	int edges = 0;
	for(int i = l + 1; i <= x; i++) {
		if(find(i) != find(p)) {
			ask[i] = 2;
			edges++;
		}
	}

	if(memo.count(ask)) {
		return memo[ask] < b * edges;
	}
	q++;
	if(q > 2000) assert(0);
	cout << "? ";
	for(int i = 1; i <= n; i++) {
		cout << ask[i] << " ";
	}
	cout << endl;

	int z;
	cin >> z;
	memo[ask] = z;
	return z < b * edges;
}	

int main() {
	cin.tie(0); ios_base::sync_with_stdio(0);

	cin >> n;

	for(int i = 1; i <= n; i++) par[i] = i, sz[i] = 1;

	cout << "? 1 2 ";
	for(int i = 3; i <= n; i++) cout << "0 ";
	cout << endl;

	cin >> a; 

	for(int i = 1; i <= n && b == 0; i++) {
		cout << "? ";
		for(int j = 1; j <= n; j++) {
			if(i != j) cout << 2 << " ";
			else cout << 1 << " ";
		}
		cout << endl;

		int z;
		cin >> z;

		if(a * (n - 1) != z) {
			// a * x + b * y = z
			// a * j + b * (n - 1 - j) = z
			// b = (z - a * j) / (n - 1 - j)
			for(int j = 0; j <= n - 1; j++) {
				if((z - a * j) % (n - 1 - j) == 0) {
					b = (z - a * j) / (n - 1 - j);
					break;
				} 
			}
			if(a > b) swap(a, b);
		}
		
	}

	if(b == 0) {
		cout << "! " << n - 1 << '\n';
		for(int i = 2; i <= n; i++) {
			cout << 1 << " " << i << '\n';
		}
		cout << flush;

		return 0;
	}

	// cout << a << " " << b << endl;



	int ones = 0;
	vector<pair<int,int>> edges;
	for(int i = 1; i <= n && ones < n - 1; i++) {
		int z = i;
		while(1) {
			int l = z + 1, r = n, x = -1;
			while(l <= r) {
				int mid = (l + r) / 2;
				if(found(i, z, mid)) {
					r = mid - 1, x = mid; 
				} else {
					l = mid + 1;
				}
			}
			z = x;
			ones += x != -1;
			if(x == -1) break;
			edges.push_back({i, x});
			merge(i, x);
			if(ones == n - 1) break;
		}
	}

	cout << "! " << n - 1 << '\n';

	set<int> parents;
	for(int i = 1; i <= n; i++) {
		parents.insert(find(i));
	}
	
	for(int i = 1; i <= n && edges.size() < n - 1; i++) {
		if(merge(find(i), *parents.begin())) {
			edges.push_back({*parents.begin(), find(i)});
			assert(*parents.begin() < find(i));
		}
	}

	assert(edges.size() == n - 1);
	for(auto [u, v] : edges) {
		if(u > v) cout << v << " " << u << '\n';
		else cout << u << " " << v << '\n';
	}
	cout << flush;
 
}