#include <bits/stdc++.h>
using namespace std;
const int N = 805;
template <typename T>
inline void read(T &AKNOI) {
  T x = 0, flag = 1;
  char ch = getchar();
  while (!isdigit(ch)) {
    if (ch == '-') flag = -1;
    ch = getchar();
  }
  while (isdigit(ch)) {
    x = x * 10 + ch - '0';
    ch = getchar();
  }
  AKNOI = flag * x;
}
int n, p[N], pos[N];
int a[N], vis[N];
int rm[9][N];
vector<int> q[10], tmp;
void WoW() {
  bool flag = (p[1] <= n / 2);
  printf("! ");
  for (int i = 1; i <= n; ++i) {
    printf("%d ", flag ? p[i] : n - p[i] + 1);
  }
  printf("\n");
  exit(0);
}
inline bool Query(vector<int> &vec) {
  printf("? %d ", vec.size());
  for (auto i : vec) {
    printf("%d ", i);
  }
  printf("\n");
  fflush(stdout);
  int x;
  read(x);
  return x;
}
inline bool Query(vector<int> &vec, int x) {
  vec.push_back(x);
  x = Query(vec);
  vec.pop_back();
  return x;
}
void Brute(int x, int y, bool flag) {
  tmp.clear();
  for (int i = 1; i <= n; ++i) {
    if (p[i]) continue;
    tmp.push_back(i);
  }
  for (int i = 0, sz = tmp.size(); i < sz; ++i) {
    int z = tmp[i];
    swap(tmp[i], tmp[sz - 1]);
    tmp.pop_back();
    if (Query(tmp)) {
      (pos[x] ? pos[y] : pos[x]) = z;
    }
    tmp.push_back(z);
    swap(tmp[i], tmp[sz - 1]);
  }
  if (flag) {
    if (x % 2 != rm[2][pos[x]]) {
      swap(pos[x], pos[y]);
    }
  }
  p[pos[x]] = x;
  p[pos[y]] = y;
  if (n == x * 2) WoW();
}
void DFS(int x, int rem, int cnt, int mod) {
  if (x > 8) {
    if (cnt == mod - 1 && q[rem].size() == 0) {
      for (int i = 1; i <= 8; ++i) {
        if (vis[i]) q[rem].push_back(pos[a[i]]);
      }
    }
    return;
  }
  DFS(x + 1, rem, cnt, mod);
  vis[x] = 1;
  DFS(x + 1, (rem + a[x]) % mod, cnt + 1, mod);
  vis[x] = 0;
}
void Group(int mod) {
  for (int i = 0; i < mod; ++i) {
    q[i].clear();
  }
  DFS(1, 0, 0, mod);
}
void GetRem(int mod) {
  Group(mod);
  for (int i = 1; i <= n; ++i) {
    if (p[i]) continue;
    bool flag = 0;
    for (int j = 0; j < mod - 1; ++j) {
      if (Query(q[j], i)) {
        rm[mod][i] = (mod - j) % mod;
        flag = 1;
        break;
      }
    }
    if (!flag) {
      rm[mod][i] = 1;
    }
  }
}
void solve() {
  read(n);
  Brute(1, n, 0);
  tmp.clear();
  tmp.push_back(pos[1]);
  for (int i = 1; i <= n; ++i) {
    if (p[i]) continue;
    tmp.push_back(i);
    rm[2][i] = Query(tmp);
    tmp.pop_back();
  }
  Brute(2, n - 1, 1);
  Brute(3, n - 2, 1);
  Brute(4, n - 3, 1);
  for (int i = 1; i <= 4; ++i) {
    a[i] = i;
    a[4 + i] = n - i + 1;
  }
  GetRem(3);
  GetRem(5);
  GetRem(7);
  Group(4);
  for (int i = 1; i <= n; ++i) {
    if (p[i]) continue;
    if (rm[2][i] == 0) {
      rm[4][i] = (Query(q[0], i) ? 0 : 2);
    } else if (rm[2][i] == 1) {
      rm[4][i] = (Query(q[1], i) ? 3 : 1);
    }
  }
  Group(8);
  for (int i = 1; i <= n; ++i) {
    if (p[i]) continue;
    if (rm[4][i] == 0) {
      rm[8][i] = (Query(q[0], i) ? 0 : 4);
    } else if (rm[4][i] == 1) {
      rm[8][i] = (Query(q[3], i) ? 5 : 1);
    } else if (rm[4][i] == 2) {
      rm[8][i] = (Query(q[2], i) ? 6 : 2);
    } else if (rm[4][i] == 3) {
      rm[8][i] = (Query(q[1], i) ? 7 : 3);
    }
  }
  for (int i = 1; i <= n; ++i) {
    if (p[i]) continue;
    p[i] = (rm[3][i] * 280 + rm[5][i] * 336 + rm[7][i] * 120 + rm[8][i] * 105) %
           840;
    if (p[i] < 0) p[i] += 840;
  }
  WoW();
}
int main() {
  solve();
  return 0;
}
