/************************************************* * Interactive solver for the “P_i + P_j = P_k” game * ------------------------------------------------- * protocol * • judge sends: T * • loop T times * judge sends: N (prime, 5 ≤ N) * we may send up to 3N queries * 1 i j (1 ≤ i,j ≤ N, i≠j) * flush * judge answers: k (1..N) or -1 * finally * 2 P1 P2 ... PN * flush *************************************************/ #include using namespace std; static constexpr long long INF64 = (1LL << 60); /* ---------- small helper ------------- */ void flush_out() { cout << std::flush; } int ask(int i, int j) { // send query and read reply cout << "1 " << i << ' ' << j << '\n'; flush_out(); int k; if (!(cin >> k)) exit(0); // judge terminated return k; } void answer(const vector& P) { cout << "2"; for (int x : P) cout << ' ' << x; cout << '\n'; flush_out(); } /* ---------- main logic per test case ----------- */ struct Equation { int a, b, c; }; // Pa + Pb = Pc void solve_case(int N) { int r = 1, s = 2; // two star centres vector eqs; eqs.reserve(2*N); /* ---- first star centred at r ---- */ for (int i = 1; i <= N; ++i) if (i != r) { int k = ask(r, i); if (k != -1) eqs.push_back({r, i, k}); } /* ---- second star centred at s ---- */ for (int i = 1; i <= N; ++i) if (i != s) { int k = ask(s, i); if (k != -1) eqs.push_back({s, i, k}); } /* ---- propagate α so that P_i = μ + α_i · λ ---- */ vector alpha(N + 1, INF64); // 1-based alpha[r] = 0; alpha[s] = 1; bool updated = true; while (updated) { updated = false; for (const auto& e : eqs) { long long A = alpha[e.a], B = alpha[e.b], C = alpha[e.c]; if (A != INF64 && B != INF64 && C == INF64) { alpha[e.c] = A + B; updated = true; } else if (A != INF64 && C != INF64 && B == INF64) { alpha[e.b] = C - A; updated = true; } else if (B != INF64 && C != INF64 && A == INF64) { alpha[e.a] = C - B; updated = true; } } } /* 所有点都应已确定 */ for (int i = 1; i <= N; ++i) if (alpha[i] == INF64) { cerr << "alpha unresolved at " << i << endl; exit(1); } long long amin = *min_element(alpha.begin() + 1, alpha.end()); long long amax = *max_element(alpha.begin() + 1, alpha.end()); long long denom = amax - amin; // >0 long long numer = N - 1; /* λ 只可能是 ± numer/denom */ if (numer % denom != 0) { cerr << "lambda not integral???\n"; exit(1); } long long lam_abs = numer / denom; auto try_build = [&](long long lam) -> optional> { long long mu = 1 - amin * lam; // 使最小值映射到 1 vector P(N + 1); vector seen(N + 1, 0); for (int i = 1; i <= N; ++i) { long long val = mu + alpha[i] * lam; if (val < 1 || val > N) return {}; // out of range P[i] = (int)val; if (seen[P[i]]) return {}; // duplicate seen[P[i]] = 1; } return P; }; auto cand = try_build( lam_abs ); if (!cand) cand = try_build( -lam_abs ); // opposite direction if (!cand) { cerr << "No consistent permutation found\n"; exit(1); } answer(*cand); } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int T; if (!(cin >> T)) return 0; while (T--) { int N; cin >> N; solve_case(N); /* judge may respond something; ignore */ int verdict; if (!(cin >> verdict)) break; // finished normally if (verdict != 1) break; // 1 = OK (typical); else stop } return 0; }