#include namespace { #pragma GCC diagnostic ignored "-Wunused-function" #include #pragma GCC diagnostic warning "-Wunused-function" using namespace std; using namespace atcoder; #define rep(i,n) for(int i = 0; i < (int)(n); i++) #define rrep(i,n) for(int i = (int)(n) - 1; i >= 0; i--) #define all(x) begin(x), end(x) #define rall(x) rbegin(x), rend(x) template bool chmax(T& a, const T& b) { if (a < b) { a = b; return true; } else return false; } template bool chmin(T& a, const T& b) { if (b < a) { a = b; return true; } else return false; } using ll = long long; using P = pair; using VI = vector; using VVI = vector; using VL = vector; using VVL = vector; } int main() { ios::sync_with_stdio(false); cin.tie(0); int n; cin >> n; VI ord(n); rep(i, n) ord[i] = i; bool found = false; rep(i, n) { cout << "?"; rep(j, n) cout << ' ' << int(i == j); cout << endl; int res; cin >> res; if (res == 1) { swap(ord[i], ord[0]); found = true; } } assert(found); auto cmp = [&](int i, int j) { static VI a; a.assign(n, 0); a[i] = 1; a[j] = 2; cout << "?"; rep(j, n) cout << ' ' << a[j]; cout << endl; int res; cin >> res; return res == 3; }; auto dfs = [&](auto&& self, int l, int r) -> void { if (r - l == 1) return; int c = (l + r) / 2; self(self, l, c); self(self, c, r); static VI d1, d2; d1.assign(ord.begin() + l, ord.begin() + c); d2.assign(ord.begin() + c, ord.begin() + r); auto itw = ord.begin() + l; auto it2 = d2.begin(); for (int i : d1) { while (it2 != d2.end() && cmp(*it2, i)) { *itw++ = *it2++; } *itw++ = i; } }; dfs(dfs, 1, n); VI p(n); rep(i, n) p[ord[i]] = i + 1; cout << "! "; rep(i, n) cout << p[i] << " \n"[i + 1 == n]; }