Problem: cf2013_c
Difficulty: medium
Categories: greedy, data structures
Time limit: 2000 ms, memory limit: 256 MB

Dimash learned that Mansur wrote something very unpleasant about him to a friend, so he decided to find out his password at all costs and discover what exactly he wrote.

Believing in the strength of his password, Mansur stated that his password — is a binary string of length $n$. He is also ready to answer Dimash's questions of the following type:

Dimash says a binary string $t$, and Mansur replies whether it is true that $t$ is a substring of his password.

Help Dimash find out the password in no more than $2n$ operations; otherwise, Mansur will understand the trick and stop communicating with him.

Input

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

Interaction

At the beginning of each test case, first read $n$ ($1 \le n \le 100$) — the size of the binary string. Then proceed to guessing it.

To guess each string $s$, you can make no more than $2n$ queries of the following type:

* "? t", where $t$ is a binary string such that ($1 \le |t| \le n$).

In response to this query, you will receive $1$ if $t$ is a substring of $s$, and $0$ otherwise.

Once you receive the answer, output a single string in the following format:

* "! s", where $s$ is a binary string of size $n$.

After that, proceed to solve the next test case.

If you make an incorrect attempt or exceed the limit of $2n$ attempts, you will receive $-1$ instead of an answer and get the verdict Wrong answer. In this case, your program should terminate immediately to avoid undefined verdicts.

After outputting the queries, do not forget to output a newline character and flush the output buffer. Otherwise, you will receive the verdict Solution "hung". To flush the buffer, use:

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

Example

Input

```
4
3

0

0

1

4

4

2
```

Output

```
? 00

? 000

? 010

! 010

! 1100

! 0110

! 10
```

Note

In the first example, the string $010$ is given. Therefore, the answers to the queries are as follows:

"? 00" $00$ is not a substring of $010$, so the answer is $0$.

"? 000" $000$ is not a substring, so the answer is $0$.

"? 010" $010$ is a substring, so the answer is $1$.

In the second example, the string is $1100$, in the third $0110$, and in the fourth $10$.

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



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();
    
    
    
    vector<string> cases;
    cases.reserve(t);
    for (int i = 0; i < t; i++) {
        string s = inf.readToken();
        cases.push_back(s);
        
        query_limit += 2LL * s.length();
    }

    
    log_metrics();

    
    cout << t << endl;

    for (const string& s : cases) {
        int n = (int)s.length();
        
        
        cout << n << endl;

        bool solved = false;
        while (!solved) {
            
            if (queries % 10 == 0) log_metrics();

            
            if (queries > HARD_CAP) {
                finish(_pe, "Hard query limit exceeded");
            }

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

            if (type == "!") {
                
                string guess;
                if (!(cin >> guess)) {
                    finish(_wa, "Unexpected EOF after '!'");
                }
                
                if (guess == s) {
                    solved = true; 
                } else {
                    finish(_wa, format("Incorrect password. Expected '%s', found '%s'", s.c_str(), guess.c_str()));
                }
            } else if (type == "?") {
                
                string t_guess;
                if (!(cin >> t_guess)) {
                    finish(_wa, "Unexpected EOF after '?'");
                }
                
                queries++;
                
                bool found = false;
                
                
                
                if (t_guess.length() <= s.length()) {
                    if (s.find(t_guess) != string::npos) {
                        found = true;
                    }
                }
                
                
                cout << (found ? 1 : 0) << endl;
            } else {
                
                finish(_pe, format("Invalid token '%s'. Expected '?' or '!'", type.c_str()));
            }
        }
    }

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


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

using namespace std;


static long long total_queries = 0;
static long long total_limit = 0;
static bool metrics_logged = false;


void log_metrics() {
    if (metrics_logged) return;
    metrics_logged = true;
    
    
    if (total_limit == 0) total_limit = 1;
    
    tout << "queries=" << total_queries << endl;
    tout << "query_limit=" << total_limit << endl;
}


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


string get_complement(string s) {
    for(char &c : s) c = (c == '0' ? '1' : '0');
    return s;
}

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

    
    int t = inf.readInt();
    cout << t << endl; 

    for(int i = 0; i < t; ++i) {
        
        
        
        string token = inf.readToken();
        int n;
        string s_base;
        
        bool is_binary = true;
        if (token.empty()) is_binary = false;
        for(char c : token) if(c != '0' && c != '1') is_binary = false;

        
        
        
        if(!is_binary) {
            n = stoi(token);
            
            s_base = "";
            for(int k=0; k<n; ++k) s_base += (rnd.next(2) ? '1' : '0');
        } else {
            s_base = token;
            n = s_base.length();
        }

        
        
        
        set<string> candidates;
        candidates.insert(s_base);
        candidates.insert(get_complement(s_base));
        string s_rev = s_base; 
        reverse(s_rev.begin(), s_rev.end());
        candidates.insert(s_rev);
        candidates.insert(get_complement(s_rev));
        
        
        cout << n << endl; 
        
        
        long long case_limit = 2 * n;
        total_limit += case_limit;
        
        long long case_queries = 0;
        bool solved = false;

        
        while(true) {
            
            if (total_queries > 500000) finish(_pe, "Total hard query limit exceeded");

            string type;
            if (!(cin >> type)) finish(_wa, "Unexpected EOF from solution");

            if (type == "?") {
                case_queries++;
                total_queries++;
                
                
                if (case_queries > case_limit) {
                    finish(_wa, "Too many queries for this test case");
                }
                
                string q_str;
                cin >> q_str;
                
                
                if (q_str.length() < 1 || q_str.length() > (size_t)n) {
                    finish(_pe, "Invalid query string length");
                }
                
                
                int yes_cnt = 0;
                int no_cnt = 0;
                for(const string& cand : candidates) {
                    if(cand.find(q_str) != string::npos) yes_cnt++;
                    else no_cnt++;
                }

                
                bool ans = (yes_cnt >= no_cnt);
                cout << (ans ? 1 : 0) << endl;

                
                auto it = candidates.begin();
                while(it != candidates.end()) {
                    bool has = (it->find(q_str) != string::npos);
                    if (has != ans) {
                        it = candidates.erase(it);
                    } else {
                        ++it;
                    }
                }
                
                
                if(candidates.empty()) finish(_fail, "Interactor internal error: valid set empty");

            } else if (type == "!") {
                string ans_str;
                cin >> ans_str;
                
                
                if (candidates.count(ans_str)) {
                    solved = true;
                } else {
                    finish(_wa, "Wrong answer");
                }
                break;
            } else {
                finish(_pe, "Invalid query type");
            }
        }
        
        if (!solved) finish(_wa, "Loop exited without solution");
    }

    finish(_ok, "All cases passed");
    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");

    
    int t = opt<int>("t", rnd.next(10, 50));
    
    t = max(1, min(100, t));

    
    int fixed_n = opt<int>("n", -1);

    cout << t << endl;

    for (int i = 0; i < t; ++i) {
        int n;
        if (fixed_n != -1) {
            n = fixed_n;
        } else {
            
            int p = rnd.next(100);
            if (p < 10) n = rnd.next(1, 5);         
            else if (p < 30) n = rnd.next(6, 20);   
            else if (p < 75) n = rnd.next(21, 70);  
            else n = rnd.next(71, 100);             
        }
        
        
        n = max(1, min(100, n));

        if (mode == "adp") {
            
            cout << n << endl;
        } else {
            
            string s = "";
            int type = rnd.next(10);
            
            if (type <= 2) { 
                
                for (int j = 0; j < n; ++j) s += (char)('0' + rnd.next(2));
            } else if (type == 3) {
                
                s = string(n, '0');
            } else if (type == 4) {
                
                s = string(n, '1');
            } else if (type == 5) {
                
                int start = rnd.next(2);
                for (int j = 0; j < n; ++j) s += (char)('0' + (start ^ (j & 1)));
            } else if (type == 6) {
                
                if (n == 1) {
                    s += (char)('0' + rnd.next(2));
                } else {
                    int split = rnd.next(1, n - 1);
                    int first = rnd.next(2);
                    for (int j = 0; j < split; ++j) s += (char)('0' + first);
                    for (int j = split; j < n; ++j) s += (char)('0' + (1 - first));
                }
            } else if (type == 7) {
                
                int mainBit = rnd.next(2);
                for (int j = 0; j < n; ++j) {
                    if (rnd.next(10) == 0) s += (char)('0' + (1 - mainBit));
                    else s += (char)('0' + mainBit);
                }
            } else if (type == 8) {
                
                if (n < 4) {
                    for (int j = 0; j < n; ++j) s += (char)('0' + rnd.next(2));
                } else {
                    int len = rnd.next(2, n / 2);
                    string pat = "";
                    for (int j = 0; j < len; ++j) pat += (char)('0' + rnd.next(2));
                    for (int j = 0; j < n; ++j) s += pat[j % len];
                }
            } else {
                
                string half = "";
                for (int j = 0; j < (n + 1) / 2; ++j) half += (char)('0' + rnd.next(2));
                s = half;
                for (int j = n / 2 - 1; j >= 0; --j) s += half[j];
            }
            cout << s << endl;
        }
    }

    return 0;
}