Problem: cf862_d
Difficulty: medium
Categories: search
Time limit: 2000 ms, memory limit: 256 MB

D. Mahmoud and Ehab and the binary string

Mahmoud and Ehab are in the fourth stage now.

Dr. Evil has a hidden binary string of length *n*. He guarantees that there is at least one '0' symbol and at least one '1' symbol in it. Now he wants Mahmoud and Ehab to find a position of any '0' symbol and any '1' symbol. In order to do this, Mahmoud and Ehab can ask Dr. Evil up to 15 questions. They tell Dr. Evil some binary string of length *n*, and Dr. Evil tells the Hamming distance between these two strings. Hamming distance between 2 binary strings of the same length is the number of positions in which they have different symbols. You can find the definition of Hamming distance in the notes section below.

Help Mahmoud and Ehab find these two positions.

You will get Wrong Answer verdict if

* Your queries doesn't satisfy interaction protocol described below.
* You ask strictly more than 15 questions and your program terminated after exceeding queries limit. Please note, that you can do up to 15 ask queries and one answer query.
* Your final answer is not correct.

You will get Idleness Limit Exceeded if you don't print anything or if you forget to flush the output, including for the final answer (more info about flushing output below).

If you exceed the maximum number of queries, You should terminate with 0, In this case you'll get Wrong Answer, If you don't terminate you may receive any verdict because you'll be reading from a closed stream.

Input

The first line of input will contain a single integer *n* (2 ≤ *n* ≤ 1000) — the length of the hidden binary string.

Output

To print the final answer, print "! pos0 pos1" (without quotes), where *pos*0 and *pos*1 are positions of some '0' and some '1' in the string (the string is 1-indexed). Don't forget to flush the output after printing the answer!

Interaction

To ask a question use the format "? s" (without quotes), where *s* is a query string. Don't forget to flush the output after printing a query!

After each query you can read a single integer from standard input — the Hamming distance between the hidden string and the query string.

To flush the output you can use:-

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

Example

Input

```
3  
2  
1  
3  
2  
1  
0
```

Output

```? 000? 001? 010? 011? 100? 101! 2 1
```

Note

Hamming distance definition: [link omitted]

In the first test case the hidden binary string is 101, The first query is 000, so the Hamming distance is 2. In the second query the hidden string is still 101 and query is 001, so the Hamming distance is 1.

After some queries you find that symbol at position 2 is '0' and symbol at position 1 is '1', so you print "! 2 1".

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


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




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


template <typename... Args>
void finish(TResult verdict, const char* fmt, Args... args) {
    log_metrics();
    quitf(verdict, fmt, args...);
}

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

    
    
    int n = inf.readInt(2, 1000, "n");
    string hidden_s = inf.readToken("[01]+", "hidden_s");

    
    if ((int)hidden_s.length() != n) {
        finish(_fail, "Hidden string length (%d) does not match n (%d)", (int)hidden_s.length(), n);
    }
    bool has0 = false, has1 = false;
    for (char c : hidden_s) {
        if (c == '0') has0 = true;
        if (c == '1') has1 = true;
    }
    if (!has0 || !has1) {
        finish(_fail, "Hidden string must contain at least one '0' and one '1'");
    }

    
    cout << n << endl;
    
    
    log_metrics();

    
    
    int hard_cap = 300; 

    while (true) {
        
        if (queries > hard_cap) {
            finish(_pe, "Hard query limit exceeded (%d)", hard_cap);
        }

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

        if (token == "!") {
            
            int p0, p1;
            if (!(cin >> p0 >> p1)) {
                finish(_wa, "Unexpected EOF reading answer positions");
            }
            
            
            if (p0 < 1 || p0 > n || p1 < 1 || p1 > n) {
                finish(_wa, "Answer positions %d %d out of range [1, %d]", p0, p1, n);
            }
            
            
            char c0 = hidden_s[p0 - 1];
            char c1 = hidden_s[p1 - 1];
            
            if (c0 != '0') {
                finish(_wa, "Position %d is '%c', expected '0'", p0, c0);
            }
            if (c1 != '1') {
                finish(_wa, "Position %d is '%c', expected '1'", p1, c1);
            }
            
            finish(_ok, "Correct! Found 0 at %d, 1 at %d", p0, p1);
        } else {
            
            string qs;
            if (token == "?") {
                
                if (!(cin >> qs)) {
                    finish(_wa, "Unexpected EOF reading query string after '?'");
                }
            } else {
                
                
                qs = token;
            }
            
            
            if ((int)qs.length() != n) {
                finish(_wa, "Query string length %d, expected %d", (int)qs.length(), n);
            }
            
            int dist = 0;
            for (int i = 0; i < n; i++) {
                if (qs[i] != '0' && qs[i] != '1') {
                    finish(_wa, "Query string contains invalid character '%c'", qs[i]);
                }
                if (qs[i] != hidden_s[i]) {
                    dist++;
                }
            }
            
            
            queries++;
            
            
            if (queries % 5 == 0) log_metrics();
            
            
            cout << dist << endl;
        }
    }

    return 0;
}


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

using namespace std;

static long long queries = 0;
static const long long query_limit = 15;

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

static string make_hidden_string(int n, uint64_t seed) {
    mt19937 rng((uint32_t)(seed ^ (seed >> 32)));
    string s(n, '0');
    for (int i = 0; i < n; i++) s[i] = (rng() & 1) ? '1' : '0';
    bool has0 = false, has1 = false;
    for (char ch : s) {
        has0 |= (ch == '0');
        has1 |= (ch == '1');
    }
    if (!has0) s[0] = '0';
    if (!has1) s[n - 1] = '1';
    if (n == 1) s[0] = '0';
    return s;
}

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

    int n = inf.readInt(2, 1000, "n");
    string hidden_s;
    if (!inf.seekEof()) hidden_s = inf.readToken();
    if (hidden_s.empty()) {
        uint64_t seed = (uint64_t)hash<string>{}(string(argv[1]));
        seed ^= (uint64_t)n * 0x9e3779b97f4a7c15ULL;
        hidden_s = make_hidden_string(n, seed);
    }

    if ((int)hidden_s.size() != n) finish(_fail, "Hidden string length mismatch");
    bool has0 = false, has1 = false;
    for (char ch : hidden_s) {
        if (ch != '0' && ch != '1') finish(_fail, "Hidden string has invalid character");
        has0 |= (ch == '0');
        has1 |= (ch == '1');
    }
    if (!has0 || !has1) finish(_fail, "Hidden string must contain at least one 0 and one 1");

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

    const int hard_cap = 300;
    while (true) {
        if (queries > hard_cap) finish(_pe, "Hard query limit exceeded");

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

        if (token == "!") {
            int p0, p1;
            if (!(cin >> p0 >> p1)) finish(_wa, "Malformed answer");
            if (p0 < 1 || p0 > n || p1 < 1 || p1 > n) finish(_wa, "Answer indices out of range");
            if (hidden_s[p0 - 1] != '0') finish(_wa, "Wrong 0 position");
            if (hidden_s[p1 - 1] != '1') finish(_wa, "Wrong 1 position");
            finish(_ok, "OK");
        }

        string qs;
        if (token == "?") {
            if (!(cin >> qs)) finish(_wa, "Malformed query");
        } else {
            qs = token;
        }

        if ((int)qs.size() != n) finish(_wa, "Query length mismatch");
        int dist = 0;
        for (int i = 0; i < n; i++) {
            if (qs[i] != '0' && qs[i] != '1') finish(_wa, "Query has invalid character");
            if (qs[i] != hidden_s[i]) dist++;
        }
        queries++;
        if ((queries % 5) == 0) log_metrics();
        cout << dist << endl;
        cout.flush();
    }
}



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 seed_val = atoi(argv[1]);
    
    int n;
    
    
    if (seed_val == 1) n = 2;
    else if (seed_val == 2) n = 3;
    else if (seed_val == 3) n = 1000;
    else if (seed_val == 4) n = 1000;
    else {
        
        if (rnd.next(5) == 0) n = rnd.next(2, 20);
        else n = rnd.next(900, 1000);
    }
    
    
    if (mode == "adp") {
        cout << n << endl;
        return 0;
    }
    
    
    string s = "";
    
    if (seed_val == 1) {
        s = "01";
    } else if (seed_val == 2) {
        s = "100";
    } else if (seed_val == 3) {
        
        s = string(n, '1');
        s[rnd.next(n)] = '0';
    } else if (seed_val == 4) {
        
        s = string(n, '0');
        s[rnd.next(n)] = '1';
    } else {
        
        int type = rnd.next(1, 5);
        if (type == 1) {
            
            for (int i = 0; i < n; i++) 
                s += (rnd.next(2) ? '1' : '0');
        } else if (type == 2) {
            
            int k = rnd.next(1, max(1, n / 15));
            s = string(n, '1');
            for (int i = 0; i < k; i++) s[i] = '0';
            shuffle(s.begin(), s.end());
        } else if (type == 3) {
            
            int k = rnd.next(1, max(1, n / 15));
            s = string(n, '0');
            for (int i = 0; i < k; i++) s[i] = '1';
            shuffle(s.begin(), s.end());
        } else if (type == 4) {
            
            s = string(n, '0');
            for (int i = 0; i < n / 2; i++) s[i] = '1';
            shuffle(s.begin(), s.end());
        } else {
            
            char cur = rnd.next(2) ? '1' : '0';
            while (s.length() < n) {
                int len = rnd.next(1, max(1, (int)(n - s.length())));
                s += string(len, cur);
                cur = (cur == '1' ? '0' : '1');
            }
        }
    }
    
    
    bool has0 = false;
    for (char c : s) if (c == '0') has0 = true;
    if (!has0) s[rnd.next(n)] = '0';
    
    bool has1 = false;
    for (char c : s) if (c == '1') has1 = true;
    if (!has1) {
        
        
        
        s[rnd.next(n)] = '1';
    }
    
    cout << n << endl;
    cout << s << endl;

    return 0;
}