#include <bits/stdc++.h>
using namespace std;
int mask = 0;
int answer = 0;
int highestMismatch = -1;
int n, x, y;
vector<int> finalCandidates;
int queryAnswer(vector<int> q) {
  int query_answer;
  cout << "? " << q.size();
  for (int i = 0; i < q.size(); i++) cout << " " << q[i];
  cout << "\n";
  fflush(stdout);
  cin >> query_answer;
  if (query_answer == -1) return -1;
  if (q.size() % 2 == 0) {
    if (query_answer == 0) return 0;
    if (query_answer == (x ^ y)) return 1;
  } else {
    if (query_answer == x) return 0;
    if (query_answer == y) return 1;
  }
  return -1;
}
pair<int, int> getSmallerRange(int l, int r) {
  vector<int> tmp;
  int mid = l + (r - l) / 2;
  for (int i = l; i <= mid; i++) tmp.push_back(finalCandidates[i]);
  if (queryAnswer(tmp) == 1) return make_pair(l, mid);
  return make_pair(mid + 1, r);
}
int main(int argc, const char* argv[]) {
  cin >> n >> x >> y;
  for (int i = 0; i < 10; i++) {
    vector<int> query;
    for (int j = 1; j <= n; j++)
      if ((j & (1 << i)) != 0) query.push_back(j);
    if (query.size() == 0) continue;
    int answerToQuery = queryAnswer(query);
    if (answerToQuery == -1) return 0;
    if (answerToQuery == 1) {
      highestMismatch = i;
      mask |= (1 << i);
    }
  }
  for (int i = 1; i <= n; i++)
    if ((i & (1 << highestMismatch)) != 0) finalCandidates.push_back(i);
  int l = 0;
  int r = (int)finalCandidates.size() - 1;
  while (true) {
    if (l == r) break;
    pair<int, int> x = getSmallerRange(l, r);
    l = x.first;
    r = x.second;
  }
  answer = finalCandidates[l];
  if (answer > (answer ^ mask)) answer = answer ^ mask;
  cout << "! " << answer << " " << (answer ^ mask);
  cout << flush;
  return 0;
}
