Problem: cf1779_e
Difficulty: medium
Categories: graph, greedy, data structures
Time limit: 1000 ms, memory limit: 256 MB

This is an interactive problem.

Anya has gathered $n$ chess experts numbered from $1$ to $n$ for which the following properties hold:

* For any pair of players one of the players wins every game against the other (and no draws ever occur);
* Transitivity does not necessarily hold — it might happen that $A$ always beats $B$, $B$ always beats $C$ and $C$ always beats $A$.

Anya does not know, for each pair, who is the player who beats the other.

To organize a tournament, Anya hosts $n-1$ games. In each game, she chooses two players. One of them wins and stays, while the other one is disqualified. After all the games are hosted only one player will remain. A player is said to be a candidate master if they can win a tournament (notice that the winner of a tournament may depend on the players selected by Anya in the $n-1$ games).

Since Anya is a curious girl, she is interested in finding the candidate masters. Unfortunately, she does not have much time. To speed up the process, she will organize up to $2n$ simuls (short for "simultaneous exhibition", in which one player plays against many).

In one simul, Anya chooses exactly one player who will play against some (at least one) of the other players. The chosen player wins all games they would win in a regular game, and the same holds for losses. After the simul finishes, Anya is only told the total number of games won by the chosen player (but not which ones). Nobody is disqualified during a simul.

Can you help Anya host simuls and determine the candidate masters?

The winning players in each pair could be changed between the simuls, but only in a way that preserves the results of all previous simuls. These changes may depend on your queries.

Interaction

Firstly, the jury sends one integer $n$ ($3 \leq n \leq 250$) which should be read — the number of players. After that, your program may ask queries or report an answer.

To ask a query, print "? $i \; s_1 s_2 \ldots s_n$" (without quotes), where $i$ is the index of the player who will play against some of the other players in the simul. $s$ is a binary string that denotes the players they play against. $i$ plays against every player $j$ for which $s_j = 1$ holds (and $s_j = 1$ should hold for at least one $1 \leq j \leq n$). Please note that $s_i = 0$ must hold since a player cannot play against themselves, otherwise, the query is considered to be incorrect.

After this, you should read an integer — the number of games player $i$ has won.

When you have identified the answer, you must print "! $c_1 c_2 \ldots c_n$" (without quotes) and terminate your program. $c$ is a binary string which represents the candidate masters. Player $i$ is a candidate master if $c_i=1$ holds, otherwise, they are not.

If you ask more than $2n$ queries or if one of the queries is malformed, the interaction terminates immediately and your program receives verdict Wrong Answer.

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.

Examples

Input

```
3

1

1

1
```

Output

```
? 1 010

? 2 001

? 3 100

! 111
```

Input

```
5

0

3

4
```

Output

```
? 5 10110

? 2 10111

? 1 01111

! 10000
```

Note

In the first example, the first query describes a simul in which player $1$ plays against player $2$ (and no one else). The answer to the query is $1$, meaning that player $1$ won the only game they played. We can conclude that $1$ beats $2$. Similarly, the second query tells us that $2$ beats $3$ and the third query tells us that $3$ beats $1$. All players are candidate masters in this case as

* Player $1$ can win the tournament if $2$ and $3$ play first. $3$ loses and leaves, while $2$ stays. $1$ then plays against $2$ and wins;
* Other players can win in the same fashion.

In the second example, the third query describes a simul in which player $1$ plays against every other player. The answer to the query is $4$, meaning that they won every game they played. It can be concluded that player $1$ also beats every other player. They can never lose, hence they are the only player who can remain at the end of every possible tournament, and the only possible candidate master.

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 n = inf.readInt();
    query_limit = 2LL * n; 

    
    log_metrics();

    
    
    vector<string> adj(n);
    for (int i = 0; i < n; ++i) {
        adj[i] = inf.readToken();
    }

    
    
    
    
    
    vector<bool> vis(n, false);
    vector<int> order;
    function<void(int)> dfs1 = [&](int u) {
        vis[u] = true;
        for (int v = 0; v < n; ++v) {
            if (adj[u][v] == '1' && !vis[v]) {
                dfs1(v);
            }
        }
        order.push_back(u);
    };

    for (int i = 0; i < n; ++i) {
        if (!vis[i]) dfs1(i);
    }

    
    
    fill(vis.begin(), vis.end(), false);
    vector<int> component;
    function<void(int)> dfs2 = [&](int u) {
        vis[u] = true;
        component.push_back(u);
        for (int v = 0; v < n; ++v) {
            
            if (adj[v][u] == '1' && !vis[v]) {
                dfs2(v);
            }
        }
    };

    if (!order.empty()) {
        dfs2(order.back());
    }

    string expected_ans(n, '0');
    for (int u : component) {
        expected_ans[u] = '1';
    }

    
    cout << n << endl; 

    
    int hard_cap = max(20000, 10 * (int)query_limit);

    while (true) {
        if (queries > hard_cap) {
            finish(_pe, "Hard query limit exceeded (infinite loop protection)");
        }

        string token;
        if (!(cin >> token)) {
            finish(_wa, "Unexpected EOF (expected '?' or '!')");
        }

        if (token == "!") {
            
            string ans;
            if (!(cin >> ans)) {
                finish(_wa, "Unexpected EOF reading answer string");
            }
            
            
            if (ans.length() != n) {
                finish(_wa, format("Answer length mismatch: expected %d, got %d", n, (int)ans.length()));
            }
            for (char c : ans) {
                if (c != '0' && c != '1') {
                    finish(_wa, "Answer string must contain only '0' and '1'");
                }
            }

            
            if (ans == expected_ans) {
                finish(_ok, "Correct answer");
            } else {
                finish(_wa, format("Incorrect answer. Expected: %s, Got: %s", expected_ans.c_str(), ans.c_str()));
            }

        } else {
            
            int u_idx = -1;
            string s;

            
            if (token == "?") {
                if (!(cin >> u_idx >> s)) {
                    finish(_wa, "Unexpected EOF reading query parameters");
                }
            } else {
                try {
                    u_idx = stoi(token);
                } catch (...) {
                    finish(_wa, "Invalid token (expected '?' or integer index)");
                }
                if (!(cin >> s)) {
                    finish(_wa, "Unexpected EOF reading query string");
                }
            }

            
            queries++;
            
            if (queries % 10 == 0) log_metrics();

            
            if (u_idx < 1 || u_idx > n) {
                finish(_wa, format("Player index %d out of bounds [1, %d]", u_idx, n));
            }
            if (s.length() != n) {
                finish(_wa, format("Query string length %d != %d", (int)s.length(), n));
            }

            bool self_play = false;
            bool non_empty = false;
            for (int j = 0; j < n; ++j) {
                if (s[j] == '1') {
                    non_empty = true;
                    if (j == u_idx - 1) self_play = true;
                } else if (s[j] != '0') {
                    finish(_wa, "Query string contains invalid characters (must be '0' or '1')");
                }
            }

            if (self_play) {
                finish(_wa, format("Player %d cannot play against themselves", u_idx));
            }
            if (!non_empty) {
                finish(_wa, "Player must play against at least one opponent");
            }

            
            
            int wins = 0;
            int u = u_idx - 1; 
            for (int v = 0; v < n; ++v) {
                if (s[v] == '1' && adj[u][v] == '1') {
                    wins++;
                }
            }

            cout << wins << endl;
        }
    }

    return 0;
}


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 const long long HARD_CAP = 50000;


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 n = inf.readInt();
    
    vector<string> adj(n);
    for (int i = 0; i < n; i++) {
        adj[i] = inf.readToken();
        
        if ((int)adj[i].length() != n) {
            quitf(_fail, "Invalid adjacency matrix in input file: row length != n");
        }
    }

    
    
    query_limit = 2LL * n;

    
    
    cout << n << endl;

    
    log_metrics();

    
    
    
    
    
    vector<vector<bool>> R(n, vector<bool>(n, false));
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            
            if (i == j || adj[i][j] == '1') {
                R[i][j] = true;
            }
        }
    }

    
    for (int k = 0; k < n; k++) {
        for (int i = 0; i < n; i++) {
            if (R[i][k]) {
                for (int j = 0; j < n; j++) {
                    if (R[k][j]) {
                        R[i][j] = true;
                    }
                }
            }
        }
    }

    
    string expected_ans = "";
    for (int i = 0; i < n; i++) {
        bool wins_tournament = true;
        for (int j = 0; j < n; j++) {
            if (!R[i][j]) {
                wins_tournament = false;
                break;
            }
        }
        expected_ans += (wins_tournament ? '1' : '0');
    }

    
    while (true) {
        
        if (queries > HARD_CAP) {
            finish(_pe, "Hard query limit exceeded (infinite loop protection)");
        }

        string type;
        if (!(cin >> type)) {
            
            finish(_pe, "Unexpected EOF while waiting for query/answer");
        }

        if (type == "!") {
            
            string ans;
            if (!(cin >> ans)) {
                finish(_pe, "Unexpected EOF reading answer string");
            }
            
            if (ans != expected_ans) {
                finish(_wa, format("Wrong Answer. Expected: %s, Found: %s", expected_ans.c_str(), ans.c_str()));
            } else {
                finish(_ok, "Correct candidate masters identified");
            }

        } else if (type == "?") {
            
            int i;
            string s;
            if (!(cin >> i >> s)) {
                finish(_pe, "Malformatted query arguments");
            }

            
            if (i < 1 || i > n) {
                finish(_wa, format("Player index %d out of range [1, %d]", i, n));
            }
            if ((int)s.length() != n) {
                finish(_wa, format("Query string length %d does not match n=%d", (int)s.length(), n));
            }
            
            bool has_opponent = false;
            for (char c : s) {
                if (c != '0' && c != '1') {
                    finish(_wa, "Query string must contain only '0' and '1'");
                }
                if (c == '1') has_opponent = true;
            }
            
            
            if (s[i-1] != '0') {
                finish(_wa, format("Player %d cannot play against themselves", i));
            }
            
            if (!has_opponent) {
                finish(_wa, "Simul must involve at least one opponent");
            }

            
            
            int wins = 0;
            int u = i - 1; 
            for (int v = 0; v < n; v++) {
                if (s[v] == '1') {
                    
                    if (adj[u][v] == '1') {
                        wins++;
                    }
                }
            }

            
            queries++;

            
            cout << wins << endl;

            
            if (queries % 50 == 0) {
                log_metrics();
            }

        } else {
            finish(_pe, "Unknown query token: " + type);
        }
    }

    return 0;
}


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

using namespace std;

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

    
    string mode = opt<string>("mode", "non");

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

    int n;
    int type = 0; 
    
    
    
    
    
    

    if (seed_idx == 1) { n = 3; type = 1; }
    else if (seed_idx == 2) { n = 3; type = 2; }
    else if (seed_idx == 3) { n = 250; type = 1; }
    else if (seed_idx == 4) { n = 250; type = 2; }
    else if (seed_idx == 5) { n = 250; type = 3; }
    else if (seed_idx == 6) { n = 250; type = 4; }
    else {
        
        n = rnd.next(3, 250);
        type = 0;
    }

    
    if (opt<int>("n", 0) != 0) n = opt<int>("n");

    
    vector<int> scc_sizes;
    if (type == 1) {
        scc_sizes = {n};
    } else if (type == 2) {
        scc_sizes.assign(n, 1);
    } else if (type == 3) {
        scc_sizes = {1, n - 1};
    } else if (type == 4) {
        scc_sizes = {n - 1, 1};
    } else {
        
        
        int m;
        int r = rnd.next(100);
        if (r < 10) m = 1;          
        else if (r < 20) m = n;     
        else m = rnd.next(1, n);    
        
        scc_sizes = rnd.partition(m, n, 1);
    }

    
    vector<int> p = rnd.perm(n); 
    vector<int> node_to_scc(n);
    vector<vector<int>> sccs(scc_sizes.size());

    int current_idx = 0;
    for (int i = 0; i < (int)scc_sizes.size(); i++) {
        for (int k = 0; k < scc_sizes[i]; k++) {
            int u = p[current_idx++];
            node_to_scc[u] = i;
            sccs[i].push_back(u);
        }
    }

    
    
    vector<string> adj(n, string(n, '0'));

    
    
    
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            if (i == j) continue;
            if (node_to_scc[i] < node_to_scc[j]) {
                adj[i][j] = '1';
                adj[j][i] = '0';
            }
        }
    }

    
    for (const auto& nodes : sccs) {
        int sz = nodes.size();
        if (sz < 2) continue;

        
        for (int i = 0; i < sz; i++) {
            int u = nodes[i];
            int v = nodes[(i + 1) % sz];
            adj[u][v] = '1';
            adj[v][u] = '0';
        }

        
        for (int i = 0; i < sz; i++) {
            for (int j = i + 1; j < sz; j++) {
                int u = nodes[i];
                int v = nodes[j];
                
                if (adj[u][v] == '0' && adj[v][u] == '0') {
                    if (rnd.next(2)) {
                        adj[u][v] = '1';
                        adj[v][u] = '0';
                    } else {
                        adj[u][v] = '0';
                        adj[v][u] = '1';
                    }
                }
            }
        }
    }

    
    cout << n << "\n";
    for (int i = 0; i < n; i++) {
        cout << adj[i] << "\n";
    }

    return 0;
}