#include <cstdio>
#include <cstdlib>
#include <cassert>
#include <cstdlib>
#include <vector>

using namespace std;

const char *secret = "8a87120bd5122e261c90";

class Sets {
private:
    int compare_calls;
    int weights_id;
public:
    long long **sets;
    int n, k, T;
    int get_compare_calls() { return compare_calls; }
    void read() {
        compare_calls = 0;
        assert(scanf("%d %d %d %d", &n, &k, &T, &weights_id) == 4);
        sets = new long long*[k];
        for (int i = 0; i < k; i++) {
            sets[i] = new long long[n];
            for (int j = 0; j < n; j++)
                assert(scanf("%lld", &sets[i][j]) == 1);
        }
    }
    int compare(int first, int second) {
        compare_calls++;
        if (!(popcount((unsigned int) first) + popcount((unsigned int) second) <= n &&
                    (first & second) == 0))
        {
            printf("%s\n-2\n", secret);
            exit(0);
        }
        long long sum = 0;
        for (int i = 0; i < n; i++)
            if ((first >> i) & 1)
                sum += sets[weights_id][i];
        for (int i = 0; i < n; i++)
            if ((second >> i) & 1)
                sum -= sets[weights_id][i];
        return (sum == 0 ? 0 : (sum < 0 ? -1 : 1));
    }
private:
    static int popcount(unsigned int a) {
        int res;
        for (res = 0; a; res += (a & 1), a >>= 1);
        return res;
    }
};

Sets s;

int identify_set(int, int, long long**);

int main(){
    s.read();    
    int ans = identify_set(s.n, s.k, s.sets);
    printf("%s\n%d\n%d\n", secret, ans, s.get_compare_calls());
}

const int MAXN = 30;

struct item {
  long long x;
  long long y;
  long long mask;
};

long long deg3[MAXN];
item *buffer;

item* calc(int n, long long* a, long long* b) {
  item *result0 = new item[deg3[n]];
  item *result1 = new item[deg3[n]];

  result0[0] = {0, 0, 0};

  for (int i = 0; i < n; i++) {
    int p[3];
    p[0] = p[1] = p[2] = 0;
    int ptr = 0;
    while (true) {
      int best = -1;
      if (p[0] != deg3[i]) {
        best = 0;
      }
      if (p[1] != deg3[i] && (best == -1 || result0[p[1]].x < result0[p[best]].x + (best - 1) * a[i])) {
        best = 1;
      }
      if (p[2] != deg3[i] && (best == -1 || result0[p[2]].x + a[i] < result0[p[best]].x + (best - 1) * a[i])) {
        best = 2;
      }
      if (best == -1) break;
      assert(ptr < deg3[n]);
      result1[ptr].x = result0[p[best]].x + (best - 1) * a[i];
      result1[ptr].y = result0[p[best]].y + (best - 1) * b[i];
      result1[ptr].mask = result0[p[best]].mask + deg3[i] * best;
      ptr++;
      p[best]++;
    }
    swap(result0, result1);
  }
  delete[] result1;
  return result0;
}

int check_set(int n, long long* a, long long* b) {
  int m = n / 2;
  item *left = calc(m, a, b);
  item *right = calc(n - m, a + m, b + m);

  int rptr = (int)deg3[n - m];
  long long bestm = -1;
  long long bestval = 1LL << 60;

  long long mask = -1;
  int zero = 0;

  
  /*
  for (int i = 0; i < deg3[m]; i++) {
    fprintf(stderr, "left[i] = (%lld, %lld, %lld)\n", left[i].x, left[i].y, left[i].mask);
  }
  for (int i = 0; i < deg3[n - m]; i++) {
    fprintf(stderr, "right[i] = (%lld, %lld, %lld)\n", right[i].x, right[i].y, right[i].mask);
  }
  */
  

  for (int i = 0; i < deg3[m]; i++) {
    while (rptr && left[i].x + right[rptr - 1].x > 0) {
      rptr--;
      if (bestval > right[rptr].y) {
        bestval = right[rptr].y;
        bestm = right[rptr].mask;
      }
    }
    if (left[i].y + bestval <= 0) {
      mask = left[i].mask + bestm * deg3[m];
      zero = 1;
      //fprintf(stderr, "When mask = %llx, x > %lld, y = %lld\n", mask, left[i].x + right[rptr].x, left[i].y + bestval);
      break;
    }
  }
  if (mask == -1) {
    rptr = deg3[n - m];
    bestval = 1LL << 60;
    for (int i = 0; i < deg3[m]; i++) {
      while (rptr && left[i].x + right[rptr - 1].x >= 0) {
        rptr--;
        if (bestval > right[rptr].y) {
          bestval = right[rptr].y;
          bestm = right[rptr].mask;
        }
      }
      if (left[i].y + bestval < 0) {
        mask = left[i].mask + bestm * deg3[m];
        zero = 0;
        //fprintf(stderr, "When mask = %llx, x >= %lld, y = %lld\n", mask, left[i].x + right[rptr].x, left[i].y + bestval);
        break;
      }
    }
  }
  delete[] left;
  delete[] right;

  if (mask == -1) {
    return -1;
  }

  int lf_mask = 0;
  int rg_mask = 0;

  for (int i = 0; i < n; i++) {
    int cur = (int)((mask / deg3[i]) % 3);
    if (cur == 2) {
      lf_mask += (1LL << i);
    }
    if (cur == 0) {
      rg_mask += (1LL << i);
    }
  }


  int res = s.compare(lf_mask, rg_mask);

  //fprintf(stderr, "check on (%08x, %08x) = %d\n", lf_mask, rg_mask, res);

  if (res > 0) {
    return 0;
  }
  if (res == 0) {
    return zero;
  }
  return 1;

}

void precalc() {
  deg3[0] = 1;
  for (int i = 1; i < MAXN; i++) {
    deg3[i] = deg3[i-1] * 3;
  }
}

int identify_set(int n, int k, long long **sets) {
  precalc();
  buffer = new item[deg3[(n + 1) / 2]];
  int cur_set = -1;
  int count = 0;

  for (int i = 0; i < k; i++) {
    if (count == 0) {
      cur_set = i;
      count = 1;
    } else {
      //fprintf(stderr, "check %d %d\n", cur_set, i);
      int res = check_set(n, sets[cur_set], sets[i]);
      if (res == -1) {
        count++;
      } else if (res == 0) {
      } else if (res == 1) {
        cur_set = i;
        count = 1;
      } else {
        assert(0);
      }
    }
  }
  assert(count != 0);
  if (count == 1) return cur_set;
  return -1;
}
