Problem: cf2179_g
Difficulty: hard
Categories: math
Time limit: 5000 ms, memory limit: 256 MB

IOI 2025 - Migrations

This is an interactive problem.

The species of penguins that Blackslex is researching lives on an island that is a grid with $n$ rows and $n$ columns. Exactly one penguin lives in each one cell of the grid.

He labelled each penguin as an integer from $1$ to $n^2$. After some time, some penguins migrated to another cell. After migration, every penguin will still be in some cell on the grid, and every cell contains exactly one penguin. He needs the current position of every penguin.

To do so, he can ask a penguin how far another penguin is from it.

Formally, for a possible grid $x$ representing the position of all penguins, denote $\operatorname{dist}(x, i, j)$ as the Manhattan distance of the penguin $i$ to the penguin $j$ in $x$$^{\text{∗}}$.

There is a hidden grid $a$ with $n$ rows and $n$ columns. You need to find a grid $b$ that satisfies

* $b$ has $n$ rows and $n$ columns.
* Each cell of $b$ contains an integer from $1$ to $n^2$, which is a penguin's label. Each integer will be in a single cell.
* For all $1 \leq i, j \leq n^2$, it holds that $\operatorname{dist}(a, i, j) = \operatorname{dist}(b, i, j)$.

To do so, you may make the following query no more than $3n^2 + 150$ times.

* Given $i$, $j$ ($1 \leq i, j \leq n^2$), receive the value of $\operatorname{dist}(a, i, j)$.

$^{\text{∗}}$Let $r_i$, $c_i$ denote the row and column that the penguin $i$ is in, and denote the same for $r_j$, $c_j$, then the Manhattan distance is $|r_i - r_j| + |c_i - c_j|$.

Input

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

The first line of each test case contains a single integer $n$ ($2 \leq n \leq 100$) — the size of the island.

It is guaranteed that the total sum of all values of $n$ across all test cases does not exceed $500$.

Interaction

To ask a query, pick two integer $i$, $j$ ($1 \leq i, j \leq n^2$) and print "? $i$ $j$" (without quotes) to a line.

You will receive a single integer, which is the distance between penguins $i$ and $j$.

You may make no more than $3n^2 + 150$ queries in each test case.

After you finish your queries, output "!" in a line, then output $n$ lines, each containing $n$ integers, the $j$-th integer on the $i$-th line is $b_{i,j}$.

Your output must satisfy the conditions given, and you may output any such $b$ if multiple are possible. Note that this is not considered a query and is not taken into account when counting the number of queries asked.

After this, proceed to the next test case.

The interactor in this task is not adaptive. In other words, the grid does not change during the interaction.

If you make more than $3n^2 + 150$ queries in a test case during an interaction, your program must terminate immediately, and you will receive the Wrong Answer verdict. Otherwise, you can get an arbitrary verdict because your solution will continue to read from a closed stream.

After printing a query do not forget to output the end of line and flush the output. Otherwise, you will get Idleness limit exceeded. To do this, use:

* fflush(stdout) or cout.flush() in C++;
* System.out.flush() in Java;
* flush(output) in Pascal;
* stdout.flush() in Python;
* see the documentation for other languages.

Example

Input

```
2
2

1

2

1

1

2

1

3

3
```

Output

```? 1 2? 1 3? 1 4? 2 3? 2 4? 3 4!
3 4
2 1? 1 8!
9 1 3
4 2 7
8 5 6
```

Note

Note that additional lines are for ease of reading. Your solution should not output these additional lines.

In the first test case, the grid $a$ is

|  |  |
| --- | --- |
| 1 | 4 |
| 2 | 3 |

In the second test case, the grid $a$ is

|  |  |  |
| --- | --- | --- |
| 9 | 1 | 3 |
| 4 | 2 | 7 |
| 8 | 5 | 6 |

The interaction is as follows.

|  |  |  |
| --- | --- | --- |
| Contestant | Judge | Description |
|  | 2 | Start of the first test case. The island has size $n=2$. |
|? 1 2 |  | The contestant asks for the distance of penguin labelled $1$ and $2$. |
|  | 1 | The distance of penguin labelled $1$ and $2$ is $1$. |
|? 1 3 |  | The contestant asks for the distance of penguin labelled $1$ and $3$. |
|  | 2 | The distance of penguin labelled $1$ and $3$ is $2$. |
|? 1 4 |  | The contestant asks for the distance of penguin labelled $1$ and $4$. |
|  | 1 | The distance of penguin labelled $1$ and $4$ is $1$. |
|? 2 3 |  | The contestant asks for the distance of penguin labelled $2$ and $3$. |
|  | 1 | The distance of penguin labelled $2$ and $3$ is $1$. |
|? 2 4 |  | The contestant asks for the distance of penguin labelled $2$ and $4$. |
|  | 2 | The distance of penguin labelled $2$ and $4$ is $2$. |
|? 3 4 |  | The contestant asks for the distance of penguin labelled $3$ and $4$. |
|  | 1 | The distance of penguin labelled $3$ and $4$ is $1$. |
|! |  | The contestant determined a possible grid $b$. |
| 3 4 |  | Note that the grid need not be exactly the same, but it must hold that $\operatorname{dist}(a, i, j) = \operatorname{dist}(b, i, j)$ for all $1 \leq i, j \leq n^2$. |
| 2 1 |  |  |
|  | 3 | Start of the second test case. The island has size $n=3$. |
|? 1 8 |  | The contestant asks for the distance of penguin labelled $1$ and $8$. |
|  | 3 | The distance of penguin labelled $1$ and $8$ is $3$. |
|! |  | The contestant determined a possible grid $b$. |
| 9 1 3 |  |  |
| 4 2 7 |  |  |
| 8 5 6 |  |  |

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());
}

struct TestCase {
    int n = 0;
    int n2 = 0;
    vector<int> ra, ca; 
};

static pair<int,int> applyTransform(int n, int k, int r, int c) {
    
    switch (k) {
        case 0: return {r, c};
        case 1: return {r, n - 1 - c};
        case 2: return {n - 1 - r, c};
        case 3: return {n - 1 - r, n - 1 - c};
        case 4: return {c, r};
        case 5: return {c, n - 1 - r};
        case 6: return {n - 1 - c, r};
        case 7: return {n - 1 - c, n - 1 - r};
        default: return {r, c};
    }
}

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

    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int t = 0;
    try {
        t = inf.readInt(1, 200, "t");
    } catch (...) {
        query_limit = 0;
        log_metrics();
        finish(_pe, "Failed to read t from hidden input");
    }

    vector<TestCase> tests;
    tests.reserve(t);

    long long totalLimit = 0;
    for (int tc = 0; tc < t; ++tc) {
        TestCase cs;
        cs.n = inf.readInt(2, 100, "n");
        cs.n2 = cs.n * cs.n;
        cs.ra.assign(cs.n2 + 1, -1);
        cs.ca.assign(cs.n2 + 1, -1);

        vector<char> seen(cs.n2 + 1, 0);
        for (int r = 0; r < cs.n; ++r) {
            for (int c = 0; c < cs.n; ++c) {
                int x = inf.readInt(1, cs.n2, "grid_label");
                if (seen[x]) {
                    query_limit = 0;
                    log_metrics();
                    finish(_pe, "Hidden input is not a permutation");
                }
                seen[x] = 1;
                cs.ra[x] = r;
                cs.ca[x] = c;
            }
        }

        totalLimit += 3LL * cs.n2 + 150;
        tests.push_back(std::move(cs));
    }

    query_limit = totalLimit;
    log_metrics(); 

    const long long hard_cap = max(200000LL, 10LL * query_limit);

    cout << t << endl; 
    for (int tc = 0; tc < t; ++tc) {
        const TestCase& cs = tests[tc];
        cout << cs.n << endl; 

        while (true) {
            string cmd;
            if (!(cin >> cmd)) {
                finish(_pe, "Unexpected EOF from contestant");
            }

            if (cmd == "?") {
                long long i_ll, j_ll;
                if (!(cin >> i_ll >> j_ll)) {
                    finish(_pe, "Malformed query: expected two integers after '?'");
                }
                if (i_ll < 1 || i_ll > cs.n2 || j_ll < 1 || j_ll > cs.n2) {
                    finish(_pe, "Query indices out of range");
                }
                int i = (int)i_ll, j = (int)j_ll;

                ++queries;
                if (queries > hard_cap) {
                    finish(_pe, "Hard cap exceeded (possible infinite loop / spam)");
                }

                int d = abs(cs.ra[i] - cs.ra[j]) + abs(cs.ca[i] - cs.ca[j]);
                cout << d << endl; 
            } else if (cmd == "!") {
                vector<int> rb(cs.n2 + 1, -1), cb(cs.n2 + 1, -1);
                vector<char> seen(cs.n2 + 1, 0);

                for (int r = 0; r < cs.n; ++r) {
                    for (int c = 0; c < cs.n; ++c) {
                        long long x_ll;
                        if (!(cin >> x_ll)) {
                            finish(_pe, "Malformed answer: not enough grid integers after '!'");
                        }
                        if (x_ll < 1 || x_ll > cs.n2) {
                            finish(_wa, "Answer contains label out of range");
                        }
                        int x = (int)x_ll;
                        if (seen[x]) {
                            finish(_wa, "Answer grid is not a permutation (duplicate label)");
                        }
                        seen[x] = 1;
                        rb[x] = r;
                        cb[x] = c;
                    }
                }

                bool ok = false;
                for (int k = 0; k < 8 && !ok; ++k) {
                    bool good = true;
                    for (int label = 1; label <= cs.n2; ++label) {
                        auto [tr, tc2] = applyTransform(cs.n, k, cs.ra[label], cs.ca[label]);
                        if (rb[label] != tr || cb[label] != tc2) {
                            good = false;
                            break;
                        }
                    }
                    if (good) ok = true;
                }

                if (!ok) {
                    finish(_wa, "Answer grid does not preserve all pairwise Manhattan distances");
                }
                break; 
            } else {
                finish(_pe, "Invalid command token (expected '?' or '!')");
            }
        }
    }

    finish(_ok, "OK"); 
    return 0;
}


Adaptive interactor (C++):

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

static void fyShuffle(vector<int>& a) {
    for (int i = (int)a.size() - 1; i > 0; --i) {
        int j = rnd.next(0, i);
        swap(a[i], a[j]);
    }
}

static vector<int> buildCellOrder(int n, int pattern) {
    vector<int> order;
    order.reserve(n * n);

    auto pushCell = [&](int r, int c) {
        order.push_back(r * n + c);
    };

    if (pattern == 0) {
        for (int r = 0; r < n; ++r)
            for (int c = 0; c < n; ++c)
                pushCell(r, c);
        return order;
    }

    if (pattern == 1) {
        for (int r = 0; r < n; ++r) {
            if (r % 2 == 0) {
                for (int c = 0; c < n; ++c) pushCell(r, c);
            } else {
                for (int c = n - 1; c >= 0; --c) pushCell(r, c);
            }
        }
        return order;
    }

    if (pattern == 2) {
        int b = rnd.next(5, 15);
        int br = (n + b - 1) / b;
        int bc = (n + b - 1) / b;
        vector<int> blocks;
        blocks.reserve(br * bc);
        for (int r = 0; r < br; ++r)
            for (int c = 0; c < bc; ++c)
                blocks.push_back(r * bc + c);
        fyShuffle(blocks);

        for (int id : blocks) {
            int r0 = (id / bc) * b;
            int c0 = (id % bc) * b;
            int r1 = min(n, r0 + b);
            int c1 = min(n, c0 + b);

            vector<int> local;
            local.reserve((r1 - r0) * (c1 - c0));
            for (int r = r0; r < r1; ++r) {
                if ((r - r0) % 2 == 0) {
                    for (int c = c0; c < c1; ++c) local.push_back(r * n + c);
                } else {
                    for (int c = c1 - 1; c >= c0; --c) local.push_back(r * n + c);
                }
            }
            if (rnd.next(0, 1) == 1) fyShuffle(local);
            order.insert(order.end(), local.begin(), local.end());
        }
        return order;
    }

    
    int top = 0, left = 0, bottom = n - 1, right = n - 1;
    while (top <= bottom && left <= right) {
        for (int c = left; c <= right; ++c) pushCell(top, c);
        for (int r = top + 1; r <= bottom; ++r) pushCell(r, right);
        if (top != bottom) {
            for (int c = right - 1; c >= left; --c) pushCell(bottom, c);
        }
        if (left != right) {
            for (int r = bottom - 1; r > top; --r) pushCell(r, left);
        }
        ++top; ++left; --bottom; --right;
    }

    
    int swaps = min((int)order.size() / 20, 500);
    for (int k = 0; k < swaps; ++k) {
        int i = rnd.next(0, (int)order.size() - 1);
        int j = rnd.next(0, (int)order.size() - 1);
        swap(order[i], order[j]);
    }
    return order;
}

static vector<int> buildGridNon(int n, long long seedValue) {
    vector<int> grid(n * n, 0);

    
    if (seedValue == 1) {
        
        if (n == 2) {
            
            
            
            grid = {1, 4, 3, 2};
            return grid;
        }
    }
    if (seedValue == 2) {
        if (n == 3) {
            
            
            
            
            grid = {9, 1, 7,
                    2, 5, 8,
                    6, 3, 4};
            return grid;
        }
    }
    if (seedValue == 3) {
        
        
    }

    int pattern = (seedValue == 3) ? 2 : (int)(seedValue % 4);
    vector<int> cellOrder = buildCellOrder(n, pattern);

    vector<int> labels(n * n);
    iota(labels.begin(), labels.end(), 1);

    
    int stylePick = (seedValue == 3) ? 1 : rnd.next(0, 2);

    if (stylePick == 0) {
        fyShuffle(labels);
        for (int k = 0; k < n * n; ++k) grid[cellOrder[k]] = labels[k];
        return grid;
    }

    if (stylePick == 1) {
        
        vector<int> pairs;
        pairs.reserve(n * n);
        vector<char> used(n * n, 0);
        for (int idx = 0; idx < n * n; ++idx) {
            if (used[idx]) continue;
            int r = idx / n, c = idx % n;
            int sidx = (n - 1 - r) * n + (n - 1 - c);
            used[idx] = 1;
            used[sidx] = 1;
            
            pairs.push_back(idx);
            if (sidx != idx) pairs.push_back(sidx);
        }
        
        
        int m = (int)pairs.size();
        int hasSingleton = (m % 2);
        int pairCount = (m - hasSingleton) / 2;
        vector<int> perm(pairCount);
        iota(perm.begin(), perm.end(), 0);
        fyShuffle(perm);

        vector<int> cellSeq;
        cellSeq.reserve(m);
        for (int id : perm) {
            int a = pairs[2 * id];
            int b = pairs[2 * id + 1];
            if (rnd.next(0, 1) == 1) swap(a, b);
            cellSeq.push_back(a);
            cellSeq.push_back(b);
        }
        if (hasSingleton) cellSeq.push_back(pairs[m - 1]);

        
        fyShuffle(labels);

        int ptr = 0;
        for (int idx : cellSeq) {
            grid[idx] = labels[ptr++];
        }

        
        vector<int> remapped(n * n, 0);
        for (int k = 0; k < n * n; ++k) {
            remapped[cellOrder[k]] = grid[k];
        }
        return remapped;
    }

    
    
    int disruptions = max(10, (n * n) / 25);
    for (int t = 0; t < disruptions; ++t) {
        int i = rnd.next(0, n * n - 1);
        int j = rnd.next(0, n * n - 1);
        swap(labels[i], labels[j]);
    }
    for (int k = 0; k < n * n; ++k) grid[cellOrder[k]] = labels[k];
    return grid;
}

int main(int argc, char* argv[]) {
    registerGen(argc, argv, 1);

    long long seedValue = 1;
    if (argc > 1) seedValue = atoll(argv[1]);

    string mode = opt<string>("mode", "non");
    int nOpt = opt<int>("n", -1);

    int n;
    if (nOpt != -1) {
        n = nOpt;
    } else {
        if (seedValue == 1) n = 2;
        else if (seedValue == 2) n = 3;
        else if (seedValue == 3) n = 100;
        else n = rnd.next(80, 100);
    }

    if (n < 2) n = 2;
    if (n > 100) n = 100;

    if (mode == "adp") {
        
        
        cout << 1 << "\n";
        cout << n << "\n";
        return 0;
    }

    if (mode != "non") {
        quitf(_fail, "unknown mode: %s", mode.c_str());
    }

    vector<int> grid = buildGridNon(n, seedValue);

    cout << 1 << "\n";
    cout << n << "\n";
    for (int r = 0; r < n; ++r) {
        for (int c = 0; c < n; ++c) {
            if (c) cout << ' ';
            cout << grid[r * n + c];
        }
        cout << "\n";
    }
    return 0;
}