Problem: cf2155_d
Difficulty: medium
Categories: greedy, math
Time limit: 2000 ms, memory limit: 256 MB

This is an interactive problem. Refer to the Interaction section below for better understanding.

There are $n$ ($2 \le n \le 40$) batteries numbered $1, 2, \ldots, n$. Some of them work while the others don't. Let $a$ be the number of batteries that work. It is guaranteed that $\mathbf{a \geq 2}$.

You are given $n$ but not $a$.

There is a flashlight which can hold two batteries and it only turns on when both batteries work. The batteries have been shuffled and you don't know which ones work and which ones don't. You can choose two batteries and try them in the flashlight.

You want to find a pair of batteries that work. However, you are worried about breaking the flashlight, so you want to limit the amount of trials you attempt.

Therefore, you should find a pair of working batteries using at most $\left \lfloor \frac{n^2}{a} \right \rfloor$ trials.

The interactor is adaptive. This means that whether battery $i$ ($1 \le i \le n$) works is not fixed and may change during the interaction. However, it is guaranteed that there exists a configuration of $a$ working batteries that is consistent with the information that you have received so far.

Input

Each test contains multiple test cases. The first line contains the number of test cases $t$ ($1 \le t \le 50$). The description of the test cases follows.

The first line of each test case contains a single integer $n$ ($2 \le n \le 40$) — the number of batteries.

It is guaranteed that the sum of $n$ over all test cases does not exceed $200$.

Interaction

The interaction for each test case begins with reading the integer $n$.

To make a query, print a single line with two integers in the following format:

* $\mathbb{u}\,\mathbb{v}$ ($1 \leq u, v \leq n$ and $u \neq v$) — the indices of the batteries you want to test.

After that, read a single integer $x$ — indicating whether the flashlight turned on after inserting those $2$ batteries. If $x=1$, the flashlight turned on. Otherwise, if $x=0$, the flashlight did not turn on.

After finding a pair of batteries that turns the flashlight on, the interaction of the test case is considered successful, and it will terminate. After that, the interaction continues with the next test case.

After printing each query do not forget to output the end of line and flush$^{\text{∗}}$ the output. Otherwise, you will get Idleness limit exceeded verdict.

If, at any interaction step, you read $-1$ instead of valid data, your solution must exit immediately. This means that your solution will receive Wrong answer because of an invalid query or any other mistake. Failing to exit can result in an arbitrary verdict because your solution will continue to read from a closed stream.

Example

Input

```
2
3

0

1
10

0

0

1
```

Output

```
1 2

2 3

1 2

1 3

1 4
```

Note

In the first test, there are $3$ batteries. Only batteries $2$ and $3$ work. Therefore, $a=2$ and we have to find a pair of batteries that work in $\lfloor \frac{n^2}{a} \rfloor = \lfloor \frac{3^2}{2} \rfloor = 4$ queries.

The interaction proceeds as follows:

|  |  |  |
| --- | --- | --- |
| Participant | Jury | Explanation |
| — | $3$ | There are $3$ batteries in this test case |
| $1$   $2$ | $0$ | The solution asks whether batteries $1$ and $2$ turn the flashlight on. The jury responds that they don't. |
| $2$   $3$ | $1$ | The solution asks whether batteries $2$ and $3$ turn the flashlight on. The jury responds that they do. A pair of batteries that work is found, so the interaction of the first test case terminates successfully. |

In the second test case, there are $10$ batteries. Only batteries $1$, $4$, $6$ and $9$ work. Therefore, $a=4$ and we have to find a pair of batteries that work in $\lfloor \frac{n^2}{a} \rfloor = \lfloor \frac{10^2}{4} \rfloor = 25$ queries.

The interaction proceeds as follows:

|  |  |  |
| --- | --- | --- |
| Participant | Jury | Explanation |
| — | $10$ | There are $10$ batteries in this test case. |
| $1$   $2$ | $0$ | The solution asks whether batteries $1$ and $2$ turn the flashlight on. The jury responds that they don't. |
| $1$   $3$ | $0$ | The solution asks whether batteries $1$ and $3$ turn the flashlight on. The jury responds that they don't. |
| $1$   $4$ | $1$ | The solution asks whether batteries $1$ and $4$ turn the flashlight on. The jury responds that they do. A pair of batteries that work is found, so the interaction of the first test case terminates successfully. |

Note that the line breaks in the example input and output are for the sake of clarity, and do not occur in the real interaction.

Non-adaptive interactor (C++):
#include "testlib.h"
#include <bits/stdc++.h>

using namespace std;

static long long queries = 0;
static long long query_limit = 0;

static void log_metrics() {
    try {
        tout << "queries=" << queries << endl;
        tout << "query_limit=" << query_limit << endl;
    } catch (...) {
    }
}

static void finish(TResult verdict, const string& msg) {
    log_metrics();
    quitf(verdict, "%s", msg.c_str());
}

int main(int argc, char** argv) {
    registerInteraction(argc, argv);
    atexit(log_metrics);

    int t = inf.readInt(1, 50, "t");
    vector<int> ns(t), as(t);
    vector<vector<int>> working_lists(t);

    long long total_limit = 0;
    for (int tc = 0; tc < t; tc++) {
        int n = inf.readInt(2, 40, "n");
        int a = inf.readInt(2, n, "a");

        vector<int> working(a);
        for (int i = 0; i < a; i++) working[i] = inf.readInt(1, n, "working");
        sort(working.begin(), working.end());
        working.erase(unique(working.begin(), working.end()), working.end());
        if ((int)working.size() != a) finish(_fail, "Hidden working set is not a-size distinct");

        ns[tc] = n;
        as[tc] = a;
        working_lists[tc] = std::move(working);

        total_limit += 1LL * n * n / a;
    }
    query_limit = total_limit;
    log_metrics();

    cout << t << endl;
    cout.flush();

    for (int tc = 0; tc < t; tc++) {
        int n = ns[tc];
        int a = as[tc];
        const vector<int>& working = working_lists[tc];
        vector<char> is_working(n + 1, 0);
        for (int v : working) is_working[v] = 1;

        long long local_limit = 1LL * n * n / a;
        long long local_queries = 0;

        cout << n << endl;
        cout.flush();

        while (true) {
            int u, v;
            if (!(cin >> u >> v)) finish(_wa, "Unexpected EOF (expected query)");

            local_queries++;
            queries++;
            if (queries % 50 == 0) log_metrics();

            if (local_queries > local_limit) {
                cout << -1 << endl;
                cout.flush();
                finish(_wa, "Query limit exceeded");
            }

            if (u < 1 || u > n || v < 1 || v > n || u == v) {
                cout << -1 << endl;
                cout.flush();
                finish(_wa, "Invalid query");
            }

            int resp = (is_working[u] && is_working[v]) ? 1 : 0;
            cout << resp << endl;
            cout.flush();
            if (resp == 1) break;
        }
    }

    finish(_ok, "All test cases passed");
}


Adaptive interactor (C++):
#include "testlib.h"

#include <algorithm>
#include <csignal>
#include <functional>
#include <iostream>
#include <string>
#include <vector>

using namespace std;

static long long queries = 0;
static long long query_limit = 0;

static void log_metrics() {
    try {
        tout << "queries=" << queries << endl;
        tout << "query_limit=" << query_limit << endl;
    } catch (...) {
    }
}

[[noreturn]] static void finish(TResult verdict, const string& msg) {
    log_metrics();
    quitf(verdict, "%s", msg.c_str());
}

static bool has_clique_at_least(const vector<unsigned long long>& adj, int n, int target) {
    if (target <= 1) return true;
    if (target > n) return false;

    const unsigned long long full = (n == 64) ? ~0ULL : ((1ULL << n) - 1ULL);

    auto popcnt = [](unsigned long long x) -> int { return __builtin_popcountll(x); };

    function<bool(unsigned long long, int)> dfs = [&](unsigned long long cand, int sz) -> bool {
        if (sz >= target) return true;
        if (cand == 0) return false;
        if (sz + popcnt(cand) < target) return false;

        
        int pivot = -1;
        int best_deg = -1;
        unsigned long long tmp = cand;
        while (tmp) {
            int u = __builtin_ctzll(tmp);
            tmp &= tmp - 1;
            int deg = popcnt(cand & adj[u]);
            if (deg > best_deg) {
                best_deg = deg;
                pivot = u;
            }
        }
        if (pivot < 0) return false;

        
        unsigned long long to_try = cand & (~adj[pivot]) & full;
        while (to_try) {
            int v = __builtin_ctzll(to_try);
            to_try &= to_try - 1;
            unsigned long long next = cand & adj[v];
            if (dfs(next, sz + 1)) return true;
            cand &= ~(1ULL << v);
            if (sz + popcnt(cand) < target) return false;
            to_try = cand & (~adj[pivot]) & full;
        }
        return false;
    };

    return dfs(full, 0);
}

int main(int argc, char** argv) {
    registerInteraction(argc, argv);
    signal(SIGPIPE, SIG_IGN);
    atexit(log_metrics);

    const int t = inf.readInt(1, 50, "t");
    vector<int> ns(t), as(t);

    long long total_limit = 0;
    for (int tc = 0; tc < t; tc++) {
        const int n = inf.readInt(2, 40, "n");
        const int a = inf.readInt(2, n, "a");
        ns[tc] = n;
        as[tc] = a;
        total_limit += 1LL * n * n / a;
    }
    query_limit = total_limit;
    log_metrics();

    cout << t << endl;
    cout.flush();

    for (int tc = 0; tc < t; tc++) {
        const int n = ns[tc];
        const int a = as[tc];
        const long long local_limit = 1LL * n * n / a;
        long long local_queries = 0;

        
        vector<unsigned long long> adj(n);
        const unsigned long long full = (n == 64) ? ~0ULL : ((1ULL << n) - 1ULL);
        for (int i = 0; i < n; i++) adj[i] = full & ~(1ULL << i);

        cout << n << endl;
        cout.flush();

        while (true) {
            int u, v;
            if (!(cin >> u >> v)) finish(_wa, "Unexpected EOF (expected query)");

            local_queries++;
            queries++;
            if (queries % 50 == 0) log_metrics();

            if (local_queries > local_limit) {
                cout << -1 << endl;
                cout.flush();
                finish(_wa, "Query limit exceeded");
            }

            if (u < 1 || u > n || v < 1 || v > n || u == v) {
                cout << -1 << endl;
                cout.flush();
                finish(_wa, "Invalid query");
            }

            int uu = u - 1;
            int vv = v - 1;
            if (((adj[uu] >> vv) & 1ULL) == 0ULL) {
                
                cout << 0 << endl;
                cout.flush();
                continue;
            }

            
            adj[uu] &= ~(1ULL << vv);
            adj[vv] &= ~(1ULL << uu);

            if (has_clique_at_least(adj, n, a)) {
                cout << 0 << endl;
                cout.flush();
                continue;
            }

            
            adj[uu] |= (1ULL << vv);
            adj[vv] |= (1ULL << uu);
            cout << 1 << endl;
            cout.flush();
            break;
        }
    }

    finish(_ok, "All test cases passed");
    return 0;
}


Test generator (C++):
#include "testlib.h"
#include <bits/stdc++.h>
using namespace std;
























struct TestCase {
    int n;
    int a;
    vector<int> working;
};

int main(int argc, char* argv[]) {
    registerGen(argc, argv, 1);
    
    
    string mode = opt<string>("mode", "non");

    const int MAX_SUM_N = 200;
    const int MAX_T = 50;

    vector<TestCase> cases;
    int current_sum_n = 0;
    
    
    long long seed = atoll(argv[1]);

    if (seed == 1) {
        
        
        
        vector<int> a_vals = {2, 5, 10, 20, 40};
        for (int a : a_vals) {
            cases.push_back({40, a, {}});
        }
    } else if (seed == 2) {
        
        
        while (cases.size() < MAX_T && current_sum_n < MAX_SUM_N) {
            int rem = MAX_SUM_N - current_sum_n;
            if (rem < 2) break;
            
            int n = rnd.next(2, min(rem, 10));
            int a = rnd.next(2, n);
            
            cases.push_back({n, a, {}});
            current_sum_n += n;
        }
    } else if (seed == 3) {
        
        
        while (cases.size() < MAX_T && current_sum_n < MAX_SUM_N) {
            int rem = MAX_SUM_N - current_sum_n;
            if (rem < 2) break;
            
            
            int n = rnd.next(max(2, min(rem, 15)), min(rem, 40));
            
            
            int limit_a = max(2, (int)sqrt(n) + 2);
            int a = rnd.next(2, min(n, limit_a));
            
            cases.push_back({n, a, {}});
            current_sum_n += n;
        }
    } else {
        
        while (cases.size() < MAX_T && current_sum_n < MAX_SUM_N) {
            int rem = MAX_SUM_N - current_sum_n;
            if (rem < 2) break;
            
            int n_max = min(rem, 40);
            int n = rnd.next(2, n_max);
            
            
            if (rnd.next(2) && n_max > 12) {
                n = rnd.next(12, n_max);
            }
            
            
            int a = rnd.next(2, n);
            int type = rnd.next(20);
            if (type == 0) a = 2;              
            else if (type == 1) a = n;         
            else if (type == 2) a = max(2, n/2); 
            
            cases.push_back({n, a, {}});
            current_sum_n += n;
        }
    }

    
    if (mode == "non") {
        for (auto &c : cases) {
            vector<int> p = rnd.perm(c.n, 1); 
            c.working.clear();
            for (int i = 0; i < c.a; ++i) {
                c.working.push_back(p[i]);
            }
            sort(c.working.begin(), c.working.end());
        }
    }

    
    cout << cases.size() << endl;
    for (const auto &c : cases) {
        if (mode == "non") {
            cout << c.n << " " << c.a << endl;
            for (int i = 0; i < c.a; ++i) {
                cout << c.working[i] << (i == c.a - 1 ? "" : " ");
            }
            cout << endl;
        } else {
            
            cout << c.n << " " << c.a << endl;
        }
    }

    return 0;
}