#include using namespace std; using ll = long long; using ld = long double; using ull = unsigned long long; #define rep(i,n) for(ll i=0;i T div_floor(T a, T b) { return a / b - ((a ^ b) < 0 && a % b); } template T div_ceil(T a, T b) { return a / b + ((a ^ b) > 0 && a % b); } template inline bool chmin(T &x, U y) { return (y < x) ? (x = y, true) : false; } template inline bool chmax(T &x, U y) { return (x < y) ? (x = y, true) : false; } template ostream &operator<<(ostream &os, const vector &a){ if (a.empty()) return os; os << a.front(); for (auto e : a | views::drop(1)){ os << ' ' << e; } return os; } void dump(auto ...vs){ ((cout << vs << ' '), ...) << endl; } bool local=false; vector ansP; void solve() { ll N; cin>>N; if (local){ ansP=vector(N,-1); rep(i,N){ cin>>ansP[i]; } } ll query_num=0; auto query=[&](ll i,ll j){ assert (i!=j); query_num++; assert(query_num<3*N); cout<<"1 "<>k; } k--; if (k<0)k++; return k; }; ll base_i=-1; rep(i,N-1){ ll r=query(i,i+1); if (r>=0){ base_i=i; break; } } if (base_i==-1){ ll r=query(N-1,0); if (r>=0){ base_i=N-1; } } assert(base_i>=0); vector nxt(N,-1); rep(j,N){ if (j==base_i)continue; nxt[j]=query(base_i,j); } vector is_start(N,true); rep(i,N){ if (nxt[i]>=0){ is_start[nxt[i]]=false; } } vector> com; rep(i,N){ if (i==base_i)continue; if (is_start[i]){ vector c; ll ni=i; while (ni>=0){ c.push_back(ni); ni=nxt[ni]; } com.push_back(c); } } sort(all(com),[](vector a,vector b){ return a.size()>b.size(); }); if (com.size()>=2){ if (com[com.size()-1].size()==com[com.size()-2].size()){ com.push_back({}); } } // dump(com.size()); // dump(com); reverse(all(com.back())); com.back().push_back(base_i); reverse(all(com.back())); vector P(N,-1); ll B=com.size(); if (B==1){ rep(j,N){ P[com[0][j]]=j+1; } cout<<2<<' '; rep(i,N){ if (i!=0)cout<<' '; cout< D(N); rep(i,B){ for (ll j:com[i]){ D[j]=i; } } vector nxtc(B,-1); vector over(B,false); rep(i,B){ if (i==0)continue; ll r=query(com[0][0],com[i][0]); if (r!=com[D[r]][0]){ over[i]=true; } nxtc[i]=D[r]; } is_start=vector(B,true); rep(i,B){ if (nxtc[i]>=0){ is_start[nxtc[i]]=false; } } rep(i,B){ if (is_start[i]){ nxtc[0]=i; ll res=query(com[0][0],com[0][1]); if (res==-1 or res!=com[i][1]){ over[0]=true; } break; } } // dump(nxtc); vector order; ll ni=B-1; while (true){ order.push_back(ni); ni=nxtc[ni]; if (ni==B-1)break; } assert(order.size()==B); ll v=count(all(over),true); rep(i,B){ ll oi=order[i]; ll s=(v*i)%B; if (s==0)s+=B; rep(j,(ll)com[oi].size()){ P[com[oi][j]]=s+B*j; } } cout<<2<<' '; rep(i,N){ if (i!=0)cout<<' '; cout<sync_with_stdio(0); ll T=1; cin>>T; while (T--){ solve(); } return 0; }