#include <bits/stdc++.h>   ///#prbgmb GCC target ( sse4.2 )      ///#pragma GCC opimize( O1 )   ///#pragma GCC opimize( O2 )      ///#pragma GCC opimize( Os )   ///#pragma GCC opimize( Ofast )   ///#pragma GCC target( avx,avx2,fma )   ///#pragma GCC target( avx2 )            ///#pragma GCC opimize( O3 )   ///#pragma GCC opimization ( unroll-loops )      using namespace std;      bool home = 0;   typedef long long ll;   typedef long double ld;      mt19937 rng((long long) (new char));      const int N = 100 + 7;   int n, edge[N][N];      int ask1(int a, int b) {     assert(a != b);     cout <<  1   << a - 1 <<     << b - 1 << endl;     int x;     if (home) {       x = edge[a][b];     } else {       cin >> x;       assert(x != -1);     }     return x;   }      int ask2(int a, vector<int> b) {     if (b.empty()) {       return 0;     }     cout <<  2   << a - 1 <<     << (int) b.size() <<    ;     for (auto &x : b) {       cout << x - 1 <<    ;     }     cout << endl;     int x;     if (home) {       x = 0;       for (auto &no : b) {         x |= edge[a][no];       }     } else {       cin >> x;       assert(x != -1);     }     return x;   }         vector<int> rec(int l, int r) {     if (l > r) {       return {};     }     if (l == r) {       return {l};     }     int m = (l + r) / 2;     auto a = rec(l, m);     auto b = rec(m + 1, r);     vector<int> c;     int pa = 0, pb = 0, sa = (int) a.size(), sb = (int) b.size();     while (pa < sa && pb < sb) {       if (ask1(a[pa], b[pb])) {         c.push_back(a[pa++]);       } else {         c.push_back(b[pb++]);       }     }     while (pa < sa) {       c.push_back(a[pa++]);     }     while (pb < sb) {       c.push_back(b[pb++]);     }     return c;   }      vector<int> g[N];   bool senpai[N];      void dfs(int a) {     senpai[a] = 1;     for (auto &b : g[a]) {       if (!senpai[b]) {         dfs(b);       }     }   }      signed main() {     if (home) {       ifstream fin( tony_stark );       fin >> n;       for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) edge[i][j] = -1;       for (int i = 1; i <= n * (n - 1) / 2; i++) {         int x, y;         fin >> x >> y;         x++;         y++;         edge[x][y] = 1;         edge[y][x] = 0;       }       for (int i = 1; i <= n; i++) {         for (int j = 1; j <= n; j++) {           if (i != j) {             assert(edge[i][j] == 0 || edge[i][j] == 1);           }         }       }     }     int tt;     if (home) tt = 1; else     cin >> tt;     while (tt--) {       if (!home) cin >> n;       auto ord = rec(1, n);       for (int i = 1; i < n; i++) {         g[ord[i - 1]].push_back(ord[i]);       }       vector<int> nodes = ord;       for (int i = n - 1; i >= 0; i--) {         while ((int) nodes.size() > i) {           nodes.pop_back();         }         int last = -1;         while (ask2(ord[i], nodes)) {           nodes.pop_back();           last = (int) nodes.size();         }         if (last != -1) {           g[ord[i]].push_back(ord[last]);         }       }       cout << 3 << endl;       for (int i = 1; i <= n; i++) {         for (int j = 1; j <= n; j++) {           senpai[j] = 0;         }         dfs(i);         for (int j = 1; j <= n; j++) {           cout << senpai[j];         }         cout << endl;       }       int ok;       cin >> ok;              for (int i = 1; i <= n; i++) {         g[i].clear();       }     }     return 0;   }