#ifdef LOCAL
//#define _GLIBCXX_DEBUG
#pragma comment(linker, "/STACK:102400000,102400000")
#endif
#pragma GCC optimize("Ofast") // Ofast 等效于 -O3 -ffast-math
#include <bits/stdc++.h>

using namespace std;

#define FAST_READ ios::sync_with_stdio(false); cin.tie(nullptr);
#ifdef LOCAL
#define see(x) cout  <<"<DBG> " << #x << ": " << (x) << endl
#endif
#ifndef LOCAL
#define see(x)
#endif

template<typename T> void dprintln(const T &t) { cout << t << endl; } // for debug use
template<typename T, typename ...Args> void dprintln(const T &t, const Args &...rest) { cout << t << ' '; dprintln(rest...); }
template<typename T> void println(const T &t) { cout << t << '\n'; }
template<typename T, typename ...Args> void println(const T &t, const Args &...rest) { cout << t << ' '; println(rest...); }

template<typename T> void print(const T &t) { cout << t << ' '; }

template<typename T, typename ...Args> void print(const T &t, const Args &...rest) { cout << t << ' '; print(rest...); }

// this overload is chosen when there's only one argument
template<class T> void scan(T &t) { cin >> t; }
template<class T, class ...Args> void scan(T &a, Args &...rest) { cin >> a; scan(rest...); }
using ll = long long;
using vl = vector<ll>;
using vi = vector<int>;
using pii = pair<int,int>;
using vb = vector<bool>;
using vpii = vector<pii>;

#define rng(i, a, b) for(int i = (a); i < (b); ++i)
#define down(i, b, a) for (int i = (b); i >= (a); i--)
#define rep(n) for(int _ = 0, __ = (int)n; _ < __; _++)
#define stp(i, a, b, c) for (int i = (a); i < (b); i += (c))
#define FOR(x, cont) for (auto &x: cont)
#define all(x) begin(x), end(x)
#define pb push_back
#define mp make_pair
#define eb emplace_back
#define SZ(x) (int)(x).size()
#define pq(T,COMP) priority_queue<T, vector<T>, COMP>
#define popcnt(x) __builtin_popcount((x))
#define SET(arr, v) memset(arr, (v), sizeof (arr))
#define UNIQ(vec) (vec).erase(unique(all(vec)), end(vec))

auto bet = [](const ll x, const ll y, const ll i) {
    return x <= i && i <= y;
};

template<typename T1, typename T2>
T1 ceil(T1 x, T2 y) { // y >= 1，是整数。需要注意 x + y - 1 是否会溢出
    return (x + y - 1) / y;
}

inline int h_bit(unsigned int x) {
    return 31 - __builtin_clz(x);
}
inline int h_bitll(unsigned long long x) {
    return 63 - __builtin_clzll(x);
}

template <typename T>
struct bit {
    vector<T> a;
    explicit bit(int n, int v = 0) {
        a.resize(n + 1);
        if(v != 0) {
            for (int i = 1; i <= n; ++i) a[i] = v;
        }
    }

    T sum(T x) {
        T res = 0;
        while (x) {
            res += a[x];
            x -= x & -x;
        }
        return res;
    }

    T sum(int l, int r) {
        if (l > r) return 0;
        return sum(r) - sum(l - 1);
    }

    void add(int x, T v) {
        while (x < a.size()) {
            a[x] += v;
            x += x & -x;
        }
    }
    void clear(){
        fill(a.begin(), a.end(), 0);
    }
};
vi get_prime(int n) {
    vi minp(n + 1), p;
    for (int i = 2; i <= n; i++) {
        if (!minp[i]) {
            minp[i] = i;
            p.pb(i);
        }
        FOR(x, p) {
            if (x <= minp[i] && x * i <= n)
                minp[x * i] = x;
            else break;
        }
    }
    return p;
}

const int mod = 998244353;

inline void add_mod(ll &x, const ll &y) {
    x += y;
    if (x >= mod) x -= mod;
}

inline ll submod(ll x, ll y) {
    return x >= y ? x - y : x - y + mod;
}

void sub_mod(ll &x, const ll y) {
    x -= y;
    if (x < 0) x += mod;
}
// alias templates
template<typename T> using vv = vector<vector<T>>;
template <typename T1, typename T2 = T1> using vp = vector<pair<T1,T2>>;
template<typename T, int n> using va = vector<array<T,n>>;

//union-find 并查集
struct UF{
    vi par;
    explicit UF(int n) {
        par.assign(n + 1, 0);
        rng (i, 1, n + 1) par[i] = i;
    }
    int find(int x) {
        return x == par[x] ? x : par[x] = find(par[x]);
    }
    void unite(int x, int y) {
        par[find(x)] = find(y);
    }
};

vi get_popcnt(int n) {
    vi res(n + 1);
    rng (i, 0, n) {
        if (i * 2 <= n) res[i * 2] = res[i];
        if ((i & 1) == 0) res[i + 1] = res[i] + 1;
    }
    return res;
}

const int N = 30, M = 1005;

///////////////////////////////////////////////////////

int main() {
    FAST_READ
#ifdef LOCAL
    ifstream in("main.in");
    cin.rdbuf(in.rdbuf());
#endif

    int n, t;
    scan(n, t);

    if (n == 1) {
        cout << "! " << (t == 1 ? 1 : 0) << endl;
        return 0;
    }

    vi sum(n + 1);
    sum[n] = t;

    int c[2]{0};
    int pre = t;

    // 在 two's complement 表示下，负数的奇偶性也可通过最后一位是0还是1来判断
    // 设翻转的区间的长度为len，反转之后此区间内有k个1,则有
    // delta = 2k - len => k = (delta + len) / 2
    auto ask = [&pre, &c](int l, int r) {
        cout << "? " << l << ' ' << r << endl;
        int res;
        cin >> res;
        int delta = res - pre;
        if ((delta & 1) == (r & 1)) c[0] ^= 1;
        else c[1] ^= 1;
        pre = res;
        return delta;
    };

    auto restore = [&c, &ask](int l, int r) {
        while (true) {
            ask(l, r);
            if (c[0] == 0 && c[1] == 0) return;
        }
    };

    auto flip = [&c, &n, &ask](int l, int r, int side) {
        while (true) {
            int delta = ask(l, r);
            if (c[side] == 1 && c[side ^ 1] == 0) {
                int len = side == 0 ? r : n - l + 1;
                return len - (delta + len) / 2;
            }
        }
    };

    auto out = [n, &sum]() {
        cout << "! ";
        rng (i, 1, n + 1) cout << sum[i] - sum[i - 1];
        cout << endl;
    };

    if (n & 1) {
        sum[1] = t - flip(2, n, 1);
        restore(2, n);
        rng (i, 2, n) {
            sum[i] = flip(i - 1, i, 0);
            restore(i - 1, i);
        }
    } else {
        rng (i, 1, n) {
            sum[i] = flip(i, i, 0);
            restore(i, i);
        }
    }

    out();

#ifdef LOCAL
    cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
    return 0;
}


#ifdef LOCAL
//#define _GLIBCXX_DEBUG
#pragma comment(linker, "/STACK:102400000,102400000")
#endif
#pragma GCC optimize("Ofast") // Ofast 等效于 -O3 -ffast-math
#include <bits/stdc++.h>

using namespace std;

#define FAST_READ ios::sync_with_stdio(false); cin.tie(nullptr);
#ifdef LOCAL
#define see(x) cout  <<"<DBG> " << #x << ": " << (x) << endl
#endif
#ifndef LOCAL
#define see(x)
#endif

template<typename T> void dprintln(const T &t) { cout << t << endl; } // for debug use
template<typename T, typename ...Args> void dprintln(const T &t, const Args &...rest) { cout << t << ' '; dprintln(rest...); }
template<typename T> void println(const T &t) { cout << t << '\n'; }
template<typename T, typename ...Args> void println(const T &t, const Args &...rest) { cout << t << ' '; println(rest...); }

template<typename T> void print(const T &t) { cout << t << ' '; }

template<typename T, typename ...Args> void print(const T &t, const Args &...rest) { cout << t << ' '; print(rest...); }

// this overload is chosen when there's only one argument
template<class T> void scan(T &t) { cin >> t; }
template<class T, class ...Args> void scan(T &a, Args &...rest) { cin >> a; scan(rest...); }
using ll = long long;
using vl = vector<ll>;
using vi = vector<int>;
using pii = pair<int,int>;
using vb = vector<bool>;
using vpii = vector<pii>;

#define rng(i, a, b) for(int i = (a); i < (b); ++i)
#define down(i, b, a) for (int i = (b); i >= (a); i--)
#define rep(n) for(int _ = 0, __ = (int)n; _ < __; _++)
#define stp(i, a, b, c) for (int i = (a); i < (b); i += (c))
#define FOR(x, cont) for (auto &x: cont)
#define all(x) begin(x), end(x)
#define pb push_back
#define mp make_pair
#define eb emplace_back
#define SZ(x) (int)(x).size()
#define pq(T,COMP) priority_queue<T, vector<T>, COMP>
#define popcnt(x) __builtin_popcount((x))
#define SET(arr, v) memset(arr, (v), sizeof (arr))
#define UNIQ(vec) (vec).erase(unique(all(vec)), end(vec))

auto bet = [](const ll x, const ll y, const ll i) {
    return x <= i && i <= y;
};

template<typename T1, typename T2>
T1 ceil(T1 x, T2 y) { // y >= 1，是整数。需要注意 x + y - 1 是否会溢出
    return (x + y - 1) / y;
}

inline int h_bit(unsigned int x) {
    return 31 - __builtin_clz(x);
}
inline int h_bitll(unsigned long long x) {
    return 63 - __builtin_clzll(x);
}

template <typename T>
struct bit {
    vector<T> a;
    explicit bit(int n, int v = 0) {
        a.resize(n + 1);
        if(v != 0) {
            for (int i = 1; i <= n; ++i) a[i] = v;
        }
    }

    T sum(T x) {
        T res = 0;
        while (x) {
            res += a[x];
            x -= x & -x;
        }
        return res;
    }

    T sum(int l, int r) {
        if (l > r) return 0;
        return sum(r) - sum(l - 1);
    }

    void add(int x, T v) {
        while (x < a.size()) {
            a[x] += v;
            x += x & -x;
        }
    }
    void clear(){
        fill(a.begin(), a.end(), 0);
    }
};
vi get_prime(int n) {
    vi minp(n + 1), p;
    for (int i = 2; i <= n; i++) {
        if (!minp[i]) {
            minp[i] = i;
            p.pb(i);
        }
        FOR(x, p) {
            if (x <= minp[i] && x * i <= n)
                minp[x * i] = x;
            else break;
        }
    }
    return p;
}

const int mod = 998244353;

inline void add_mod(ll &x, const ll &y) {
    x += y;
    if (x >= mod) x -= mod;
}

inline ll submod(ll x, ll y) {
    return x >= y ? x - y : x - y + mod;
}

void sub_mod(ll &x, const ll y) {
    x -= y;
    if (x < 0) x += mod;
}
// alias templates
template<typename T> using vv = vector<vector<T>>;
template <typename T1, typename T2 = T1> using vp = vector<pair<T1,T2>>;
template<typename T, int n> using va = vector<array<T,n>>;

//union-find 并查集
struct UF{
    vi par;
    explicit UF(int n) {
        par.assign(n + 1, 0);
        rng (i, 1, n + 1) par[i] = i;
    }
    int find(int x) {
        return x == par[x] ? x : par[x] = find(par[x]);
    }
    void unite(int x, int y) {
        par[find(x)] = find(y);
    }
};

vi get_popcnt(int n) {
    vi res(n + 1);
    rng (i, 0, n) {
        if (i * 2 <= n) res[i * 2] = res[i];
        if ((i & 1) == 0) res[i + 1] = res[i] + 1;
    }
    return res;
}

const int N = 30, M = 1005;

///////////////////////////////////////////////////////

int main() {
    FAST_READ
#ifdef LOCAL
    ifstream in("main.in");
    cin.rdbuf(in.rdbuf());
#endif

    int n, t;
    scan(n, t);

    if (n == 1) {
        cout << "! " << (t == 1 ? 1 : 0) << endl;
        return 0;
    }

    vi sum(n + 1);
    sum[n] = t;

    int c[2]{0};
    int pre = t;

    // 在 two's complement 表示下，负数的奇偶性也可通过最后一位是0还是1来判断
    // b - a = s - 2t
    auto ask = [&pre, &c](int l, int r) {
        cout << "? " << l << ' ' << r << endl;
        int res;
        cin >> res;
        int delta = res - pre;
        if ((delta & 1) == (r & 1)) c[0] ^= 1;
        else c[1] ^= 1;
        pre = res;
        return delta;
    };

    auto restore = [&c, &ask](int l, int r) {
        while (true) {
            ask(l, r);
            if (c[0] == 0 && c[1] == 0) return;
        }
    };

    auto flip = [&c, &n, &ask](int l, int r, int side) {
        while (true) {
            int delta = ask(l, r);
            if (c[side] == 1 && c[side ^ 1] == 0) {
                return ((side == 0 ? r : n - l + 1) - delta) / 2;
            }
        }
    };

    auto out = [n, &sum]() {
        cout << "! ";
        rng (i, 1, n + 1) cout << sum[i] - sum[i - 1];
        cout << endl;
    };

    if (n & 1) {
        sum[1] = t - flip(2, n, 1);
        restore(2, n);
        rng (i, 2, n) {
            sum[i] = flip(i - 1, i, 0);
            restore(i - 1, i);
        }
    } else {
        rng (i, 1, n) {
            sum[i] = flip(i, i, 0);
            restore(i, i);
        }
    }

    out();

#ifdef LOCAL
    cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
    return 0;
}


#ifdef LOCAL
//#define _GLIBCXX_DEBUG
#pragma comment(linker, "/STACK:102400000,102400000")
#endif
#pragma GCC optimize("Ofast") // Ofast 等效于 -O3 -ffast-math
#include <bits/stdc++.h>

using namespace std;

#define FAST_READ ios::sync_with_stdio(false); cin.tie(nullptr);
#ifdef LOCAL
#define see(x) cout  <<"<DBG> " << #x << ": " << (x) << endl
#endif
#ifndef LOCAL
#define see(x)
#endif

template<typename T> void dprintln(const T &t) { cout << t << endl; } // for debug use
template<typename T, typename ...Args> void dprintln(const T &t, const Args &...rest) { cout << t << ' '; dprintln(rest...); }
template<typename T> void println(const T &t) { cout << t << '\n'; }
template<typename T, typename ...Args> void println(const T &t, const Args &...rest) { cout << t << ' '; println(rest...); }

template<typename T> void print(const T &t) { cout << t << ' '; }

template<typename T, typename ...Args> void print(const T &t, const Args &...rest) { cout << t << ' '; print(rest...); }

// this overload is chosen when there's only one argument
template<class T> void scan(T &t) { cin >> t; }
template<class T, class ...Args> void scan(T &a, Args &...rest) { cin >> a; scan(rest...); }
using ll = long long;
using vl = vector<ll>;
using vi = vector<int>;
using pii = pair<int,int>;
using vb = vector<bool>;
using vpii = vector<pii>;

#define rng(i, a, b) for(int i = (a); i < (b); ++i)
#define down(i, b, a) for (int i = (b); i >= (a); i--)
#define rep(n) for(int _ = 0, __ = (int)n; _ < __; _++)
#define stp(i, a, b, c) for (int i = (a); i < (b); i += (c))
#define FOR(x, cont) for (auto &x: cont)
#define all(x) begin(x), end(x)
#define pb push_back
#define mp make_pair
#define eb emplace_back
#define SZ(x) (int)(x).size()
#define pq(T,COMP) priority_queue<T, vector<T>, COMP>
#define popcnt(x) __builtin_popcount((x))
#define SET(arr, v) memset(arr, (v), sizeof (arr))
#define UNIQ(vec) (vec).erase(unique(all(vec)), end(vec))

auto bet = [](const ll x, const ll y, const ll i) {
    return x <= i && i <= y;
};

template<typename T1, typename T2>
T1 ceil(T1 x, T2 y) { // y >= 1，是整数。需要注意 x + y - 1 是否会溢出
    return (x + y - 1) / y;
}

inline int h_bit(unsigned int x) {
    return 31 - __builtin_clz(x);
}
inline int h_bitll(unsigned long long x) {
    return 63 - __builtin_clzll(x);
}

template <typename T>
struct bit {
    vector<T> a;
    explicit bit(int n, int v = 0) {
        a.resize(n + 1);
        if(v != 0) {
            for (int i = 1; i <= n; ++i) a[i] = v;
        }
    }

    T sum(T x) {
        T res = 0;
        while (x) {
            res += a[x];
            x -= x & -x;
        }
        return res;
    }

    T sum(int l, int r) {
        if (l > r) return 0;
        return sum(r) - sum(l - 1);
    }

    void add(int x, T v) {
        while (x < a.size()) {
            a[x] += v;
            x += x & -x;
        }
    }
    void clear(){
        fill(a.begin(), a.end(), 0);
    }
};
vi get_prime(int n) {
    vi minp(n + 1), p;
    for (int i = 2; i <= n; i++) {
        if (!minp[i]) {
            minp[i] = i;
            p.pb(i);
        }
        FOR(x, p) {
            if (x <= minp[i] && x * i <= n)
                minp[x * i] = x;
            else break;
        }
    }
    return p;
}

const int mod = 998244353;

inline void add_mod(ll &x, const ll &y) {
    x += y;
    if (x >= mod) x -= mod;
}

inline ll submod(ll x, ll y) {
    return x >= y ? x - y : x - y + mod;
}

void sub_mod(ll &x, const ll y) {
    x -= y;
    if (x < 0) x += mod;
}
// alias templates
template<typename T> using vv = vector<vector<T>>;
template <typename T1, typename T2 = T1> using vp = vector<pair<T1,T2>>;
template<typename T, int n> using va = vector<array<T,n>>;

//union-find 并查集
struct UF{
    vi par;
    explicit UF(int n) {
        par.assign(n + 1, 0);
        rng (i, 1, n + 1) par[i] = i;
    }
    int find(int x) {
        return x == par[x] ? x : par[x] = find(par[x]);
    }
    void unite(int x, int y) {
        par[find(x)] = find(y);
    }
};

vi get_popcnt(int n) {
    vi res(n + 1);
    rng (i, 0, n) {
        if (i * 2 <= n) res[i * 2] = res[i];
        if ((i & 1) == 0) res[i + 1] = res[i] + 1;
    }
    return res;
}

const int N = 30, M = 1005;

///////////////////////////////////////////////////////

int main() {
    FAST_READ
#ifdef LOCAL
    ifstream in("main.in");
    cin.rdbuf(in.rdbuf());
#endif

    int n, t;
    scan(n, t);

    if (n == 1) {
        cout << "! " << (t == 1 ? 1 : 0) << endl;
        return 0;
    }

    vi sum(n + 1);
    sum[n] = t;

    int c[2]{0};
    int pre = t;

    // 在 two's complement 表示下，负数的奇偶性也可通过最后一位是0还是1来判断
    // b - a = s - 2t
    auto ask = [&pre, &c](int l, int r) {
        cout << "? " << l << ' ' << r << endl;
        int res;
        cin >> res;
        int delta = res - pre;
        if ((delta & 1) == (r & 1)) c[0] ^= 1;
        else c[1] ^= 1;
        pre = res;
        return delta;
    };

    auto restore = [&c, &ask](int l, int r) {
        while (true) {
            ask(l, r);
            if (c[0] == 0 && c[1] == 0) return;
        }
    };

    auto flip = [&c, &n, &ask](int l, int r, int side) {
        while (true) {
            int delta = ask(l, r);
            if (c[side] == 1 && c[side ^ 1] == 0) {
                return ((side == 0 ? r : n - l + 1) - delta) / 2;
            }
        }
    };

    auto out = [n, &sum]() {
        rng (i, 1, n + 1) cout << sum[i] - sum[i - 1];
        cout << endl;
    };

    if (n & 1) {
        sum[1] = t - flip(2, n, 1);
        restore(2, n);
        rng (i, 2, n) {
            sum[i] = flip(i - 1, i, 0);
            restore(i - 1, i);
        }
    } else {
        rng (i, 1, n) {
            sum[i] = flip(i, i, 0);
            restore(i, i);
        }
    }

    out();

#ifdef LOCAL
    cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
    return 0;
}


#ifdef LOCAL
//#define _GLIBCXX_DEBUG
#pragma comment(linker, "/STACK:102400000,102400000")
#endif
#pragma GCC optimize("Ofast") // Ofast 等效于 -O3 -ffast-math
#include <bits/stdc++.h>

using namespace std;

#define FAST_READ ios::sync_with_stdio(false); cin.tie(nullptr);
#ifdef LOCAL
#define see(x) cout  <<"<DBG> " << #x << ": " << (x) << endl
#endif
#ifndef LOCAL
#define see(x)
#endif

template<typename T> void dprintln(const T &t) { cout << t << endl; } // for debug use
template<typename T, typename ...Args> void dprintln(const T &t, const Args &...rest) { cout << t << ' '; dprintln(rest...); }
template<typename T> void println(const T &t) { cout << t << '\n'; }
template<typename T, typename ...Args> void println(const T &t, const Args &...rest) { cout << t << ' '; println(rest...); }

template<typename T> void print(const T &t) { cout << t << ' '; }

template<typename T, typename ...Args> void print(const T &t, const Args &...rest) { cout << t << ' '; print(rest...); }

// this overload is chosen when there's only one argument
template<class T> void scan(T &t) { cin >> t; }
template<class T, class ...Args> void scan(T &a, Args &...rest) { cin >> a; scan(rest...); }
using ll = long long;
using vl = vector<ll>;
using vi = vector<int>;
using pii = pair<int,int>;
using vb = vector<bool>;
using vpii = vector<pii>;

#define rng(i, a, b) for(int i = (a); i < (b); ++i)
#define down(i, b, a) for (int i = (b); i >= (a); i--)
#define rep(n) for(int _ = 0, __ = (int)n; _ < __; _++)
#define stp(i, a, b, c) for (int i = (a); i < (b); i += (c))
#define FOR(x, cont) for (auto &x: cont)
#define all(x) begin(x), end(x)
#define pb push_back
#define mp make_pair
#define eb emplace_back
#define SZ(x) (int)(x).size()
#define pq(T,COMP) priority_queue<T, vector<T>, COMP>
#define popcnt(x) __builtin_popcount((x))
#define SET(arr, v) memset(arr, (v), sizeof (arr))
#define UNIQ(vec) (vec).erase(unique(all(vec)), end(vec))

auto bet = [](const ll x, const ll y, const ll i) {
    return x <= i && i <= y;
};

template<typename T1, typename T2>
T1 ceil(T1 x, T2 y) { // y >= 1，是整数。需要注意 x + y - 1 是否会溢出
    return (x + y - 1) / y;
}

inline int h_bit(unsigned int x) {
    return 31 - __builtin_clz(x);
}
inline int h_bitll(unsigned long long x) {
    return 63 - __builtin_clzll(x);
}

template <typename T>
struct bit {
    vector<T> a;
    explicit bit(int n, int v = 0) {
        a.resize(n + 1);
        if(v != 0) {
            for (int i = 1; i <= n; ++i) a[i] = v;
        }
    }

    T sum(T x) {
        T res = 0;
        while (x) {
            res += a[x];
            x -= x & -x;
        }
        return res;
    }

    T sum(int l, int r) {
        if (l > r) return 0;
        return sum(r) - sum(l - 1);
    }

    void add(int x, T v) {
        while (x < a.size()) {
            a[x] += v;
            x += x & -x;
        }
    }
    void clear(){
        fill(a.begin(), a.end(), 0);
    }
};
vi get_prime(int n) {
    vi minp(n + 1), p;
    for (int i = 2; i <= n; i++) {
        if (!minp[i]) {
            minp[i] = i;
            p.pb(i);
        }
        FOR(x, p) {
            if (x <= minp[i] && x * i <= n)
                minp[x * i] = x;
            else break;
        }
    }
    return p;
}

const int mod = 998244353;

inline void add_mod(ll &x, const ll &y) {
    x += y;
    if (x >= mod) x -= mod;
}

inline ll submod(ll x, ll y) {
    return x >= y ? x - y : x - y + mod;
}

void sub_mod(ll &x, const ll y) {
    x -= y;
    if (x < 0) x += mod;
}
// alias templates
template<typename T> using vv = vector<vector<T>>;
template <typename T1, typename T2 = T1> using vp = vector<pair<T1,T2>>;
template<typename T, int n> using va = vector<array<T,n>>;

//union-find 并查集
struct UF{
    vi par;
    explicit UF(int n) {
        par.assign(n + 1, 0);
        rng (i, 1, n + 1) par[i] = i;
    }
    int find(int x) {
        return x == par[x] ? x : par[x] = find(par[x]);
    }
    void unite(int x, int y) {
        par[find(x)] = find(y);
    }
};

vi get_popcnt(int n) {
    vi res(n + 1);
    rng (i, 0, n) {
        if (i * 2 <= n) res[i * 2] = res[i];
        if ((i & 1) == 0) res[i + 1] = res[i] + 1;
    }
    return res;
}

const int N = 30, M = 1005;

bool DEBUG = false;
vi hidden, aux;
auto out =[](const vi &a) {
    copy(all(a), ostream_iterator<int>(cout, " "));
    cout << endl;
};
///////////////////////////////////////////////////////

int main() {
    FAST_READ
#ifdef LOCAL
    ifstream in("main.in");
    cin.rdbuf(in.rdbuf());
#endif

    int n, t;
    scan(n, t);

    if (n == 1) {
        cout << "! " << (t == 1 ? 1 : 0) << endl;
        return 0;
    }

    vi sum(n + 1);
    sum[n] = t;

    int c[2]{0};
    int pre = t;

    if(DEBUG) {
        srand (time (0));
        std::random_device rd;
        std::mt19937 g(rd());
        hidden.assign(n, 0);
        assert(SZ(hidden) == n);
        rng(i, 0, t) hidden[i] = 1;
        shuffle(all(hidden), g);
        aux = hidden;
        out(hidden);
    }

    // 在 two's complement 表示下，负数的奇偶性也可通过最后一位是0还是1来判断
    // 设翻转的区间的长度为len，反转之前此区间内有k个1,则有
    // delta = len - 2k => k = (len - delta) / 2
    auto ask = [&pre, &c, n](int l, int r) {
        cout << "? " << l << ' ' << r << endl;
        int res;
        if(DEBUG) {
            int which = rand() & 1;
//            dprintln(which);
            if(which == 0) {
                rng (i, 0, r) aux[i] ^= 1;
            }
            else {
                rng (i, l-1, n) aux[i] ^= 1;
            }
            res = 0;
            FOR(x, aux) res += x;
        }
        else {
            cin >> res;
        }
        int delta = res - pre;
        if ((delta & 1) == (r & 1)) c[0] ^= 1;
        else c[1] ^= 1;
        pre = res;
//        out(aux);
//        see(delta);
        return delta;
    };

    auto restore = [&c, &ask](int l, int r) {
        while (true) {
            ask(l, r);
            if (c[0] == 0 && c[1] == 0) return;
        }
    };

    auto flip = [&c, &n, &ask, &restore](int l, int r, int side) {
        while (true) {
            int delta = ask(l, r);
            if (c[side] == 1 && c[side ^ 1] == 0) {
                int len = side == 0 ? r : n - l + 1;
                return restore(l, r), (len - delta) / 2;
            }
            else{
                restore(l, r);
            }
        }
    };

    auto out = [n, &sum]() {
        cout << "! ";
        rng (i, 1, n + 1) {
//            assert(sum[i] - sum[i-1] == hidden[i-1]);
            cout << sum[i] - sum[i - 1];
        }
        cout << endl;
    };

    if (n & 1) {
        sum[1] = t - flip(2, n, 1);
//        println("sum", 1, sum[1]);
        rng (i, 2, n) {
            sum[i] = flip(i - 1, i, 0);
//            println("sum", i, sum[i]);
        }
    } else {
        rng (i, 1, n) {
            sum[i] = flip(i, i, 0);
//            println("sum", i, sum[i]);
        }
    }

    out();

#ifdef LOCAL
    cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
    return 0;
}


#include <bits/stdc++.h>

using namespace std;

const int MAX_N = 300;
bool xd[1+MAX_N];
bool rez[1+MAX_N];

void flip(int l, int r) {
	for(int i = l; i <= r; ++i)
		xd[i] ^= 1;
}

void interact(int l, int r, int &t, int &raise) {
	int t2;
	printf("? %d %d\n", l, r);
	fflush(stdout);
	scanf("%d", &t2);
	raise = t2 - t;
	t = t2;
	assert(t2 != -1);
}

void evenCase(int n, int t) {
	for(int i = 1; i <= n; ++i) {
		int x;
		interact(i, i, t, x);
		while(abs(x) % 2 != i % 2) { //flipped the bad side
			flip(i, n);
			interact(i, i, t, x);
		}
		if(abs(x) % 2 == i % 2) { // flipped my side
			flip(1, i);
			for(int j = 1; j < i; ++j) {
				if(rez[j] ^ xd[j])
					--x;
				else
					++x;
			}

			if(x == 1)
				rez[i] = (xd[i] ^ 1);
			else
				rez[i] = xd[i];
		}
	}
}

void oddCase(int n, int t) {
	int x, ti = t;
	interact(1, 2, t, x);
	while(x % 2 != 0) {
		flip(1, n);
		interact(1, 2, t, x);
	}
	flip(1, 2);
	if(x == 0) {
		if(x == 2)
			rez[1] = rez[2] = 0;
		else
			rez[1] = rez[2] = 1;

		for(int i = 3; i <= n; ++i) {
			interact(i - 1, i, t, x);
			while(abs(x) % 2 != i % 2) {
				flip(i - 1, n);
				interact(i - 1, i, t, x);
			}
			flip(1, i);
			for(int j = 3; j < i; ++j) {
				if(rez[j] ^ xd[j])
					--x;
				else
					++x;
			}

			if(x == 1)
				rez[i] = (xd[i] ^ 1);
			else
				rez[i] = xd[i];
		}

		interact(2, 3, t, x);
		while(x % 2 != 0) {
			flip(1, 3);
			interact(2, 3, t, x);
		}
		flip(2, n);
		for(int j = 3; j <= n; ++j)
			if(rez[j] ^ xd[j])
				--x;
			else
				++x;
		if(x == 1)
			rez[2] = (xd[2] ^ 1);
		else
			rez[2] = xd[2];
		rez[1] = (1 ^ rez[2]);

	} else {
		if(x == 2)
			rez[1] = rez[2] = 0;
		else
			rez[1] = rez[2] = 1;

		for(int i = 3; i <= n; ++i) {
			interact(i - 1, i, t, x);
			while(abs(x) % 2 != i % 2) {
				flip(i - 1, n);
				interact(i - 1, i, t, x);
			}
			flip(1, i);
			for(int j = 1; j < i; ++j) {
				if(rez[j] ^ xd[j])
					--x;
				else
					++x;
			}

			if(x == 1)
				rez[i] = (xd[i] ^ 1);
			else
				rez[i] = xd[i];
		}
	}
}

void finishPr(int n) {
	printf("! ");
	for(int i = 1; i <= n; ++i)
		fputc('0' + rez[i], stdout);
	fflush(stdout);
}

int main() {
#ifdef HOME
	FILE *fin = fopen("input.in", "r");
	FILE *fout = fopen("output.out", "w");
#else
	FILE *fin = stdin;
	FILE *fout = stdout;
#endif

	int n, t;
	scanf("%d%d", &n, &t);

	if(n % 2 == 0)
		evenCase(n, t);
	else if(n > 1)
		oddCase(n, t);
	else
		rez[1] = t;

	finishPr(n);

#ifdef HOME
	fclose(fin);
	fclose(fout);
#endif
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

const int MAX_N = 300;
bool xd[1+MAX_N];
bool rez[1+MAX_N];

void flip(int l, int r) {
	for(int i = l; i <= r; ++i)
		xd[i] ^= 1;
}

void interact(int l, int r, int &t, int &raise) {
	int t2;
	printf("? %d %d\n", l, r);
	fflush(stdout);
	scanf("%d", &t2);
	raise = t2 - t;
	t = t2;
	assert(t2 != -1);
}

void evenCase(int n, int t) {
	for(int i = 1; i <= n; ++i) {
		int x;
		interact(i, i, t, x);
		while(abs(x) % 2 != i % 2) { //flipped the bad side
			flip(i, n);
			interact(i, i, t, x);
		}
		if(abs(x) % 2 == i % 2) { // flipped my side
			flip(1, i);
			for(int j = 1; j < i; ++j) {
				if(rez[j] ^ xd[j])
					--x;
				else
					++x;
			}

			if(x == 1)
				rez[i] = (xd[i] ^ 1);
			else
				rez[i] = xd[i];
		}
	}
}

void oddCase(int n, int t) {
	int x, ti = t;
	interact(1, 2, t, x);
	while(x % 2 != 0) {
		flip(1, n);
		interact(1, 2, t, x);
	}
	flip(1, 2);
	if(x == 0) {
		for(int i = 3; i <= n; ++i) {
			interact(i - 1, i, t, x);
			while(abs(x) % 2 != i % 2) {
				flip(i - 1, n);
				interact(i - 1, i, t, x);
			}
			flip(1, i);
			for(int j = 3; j < i; ++j) {
				if(rez[j] ^ xd[j])
					--x;
				else
					++x;
			}

			if(x == 1)
				rez[i] = (xd[i] ^ 1);
			else
				rez[i] = xd[i];
		}

		interact(2, 3, t, x);
		while(abs(x) % 2 != 0) {
			flip(1, 3);
			interact(2, 3, t, x);
		}
		flip(2, n);
		for(int j = 3; j <= n; ++j)
			if(rez[j] ^ xd[j])
				--x;
			else
				++x;
		if(x == 1)
			rez[2] = (xd[2] ^ 1);
		else
			rez[2] = xd[2];
		rez[1] = (1 ^ rez[2]);

	} else {
		if(x == 2)
			rez[1] = rez[2] = (1 ^ xd[0]);
		else
			rez[1] = rez[2] = (0 ^ xd[1]);

		for(int i = 3; i <= n; ++i) {
			interact(i - 1, i, t, x);
			while(abs(x) % 2 != i % 2) {
				flip(i - 1, n);
				interact(i - 1, i, t, x);
			}
			flip(1, i);
			for(int j = 1; j < i; ++j) {
				if(rez[j] ^ xd[j])
					--x;
				else
					++x;
			}

			if(x == 1)
				rez[i] = (xd[i] ^ 1);
			else
				rez[i] = xd[i];
		}
	}
}

void finishPr(int n) {
	printf("! ");
	for(int i = 1; i <= n; ++i)
		fputc('0' + rez[i], stdout);
	fflush(stdout);
}

int main() {
#ifdef HOME
	FILE *fin = fopen("input.in", "r");
	FILE *fout = fopen("output.out", "w");
#else
	FILE *fin = stdin;
	FILE *fout = stdout;
#endif

	int n, t;
	scanf("%d%d", &n, &t);
	if(n % 2 == 0)
		evenCase(n, t);
	else if(n > 1)
		oddCase(n, t);
	else
		rez[1] = t;

	finishPr(n);

#ifdef HOME
	fclose(fin);
	fclose(fout);
#endif
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

const int MAX_N = 300;
bool xd[1+MAX_N];
bool rez[1+MAX_N];

void flip(int l, int r) {
	for(int i = l; i <= r; ++i)
		xd[i] ^= 1;
}

void interact(int l, int r, int &t, int &raise) {
	int t2;
	printf("? %d %d\n", l, r);
	fflush(stdout);
	scanf("%d", &t2);
	raise = t2 - t;
	t = t2;
	assert(t2 != -1);
}

void evenCase(int n, int t) {
	for(int i = 1; i <= n; ++i) {
		int x;
		interact(i, i, t, x);
		while(abs(x) % 2 != i % 2) { //flipped the bad side
			flip(i, n);
			interact(i, i, t, x);
		}
		if(abs(x) % 2 == i % 2) { // flipped my side
			flip(1, i);
			for(int j = 1; j < i; ++j) {
				if(rez[j] ^ xd[j])
					--x;
				else
					++x;
			}

			if(x == 1)
				rez[i] = (xd[i] ^ 1);
			else
				rez[i] = xd[i];
		}
	}
}

void oddCase(int n, int t) {
	int x, ti = t;
	interact(1, 2, t, x);
	while(x % 2 != 0) {
		flip(1, n);
		interact(1, 2, t, x);
	}
	flip(1, 2);
	if(x == 0) {
		for(int i = 3; i <= n; ++i) {
			interact(i - 1, i, t, x);
			while(abs(x) % 2 != i % 2) {
				flip(i - 1, n);
				interact(i - 1, i, t, x);
			}
			flip(1, i);
			for(int j = 3; j < i; ++j) {
				if(rez[j] ^ xd[j])
					--x;
				else
					++x;
			}

			if(x == 1)
				rez[i] = (xd[i] ^ 1);
			else
				rez[i] = xd[i];
		}

		interact(2, 3, t, x);
		while(abs(x) % 2 != 0) {
			flip(1, 3);
			interact(2, 3, t, x);
		}
		flip(2, n);
		for(int j = 3; j <= n; ++j)
			if(rez[j] ^ xd[j])
				--x;
			else
				++x;
		if(x == 1)
			rez[2] = (xd[2] ^ 1);
		else
			rez[2] = xd[2];
		rez[1] = (1 ^ rez[2]);

	} else {
		if(x == 2)
			rez[1] = rez[2] = (0 ^ xd[0]);
		else
			rez[1] = rez[2] = (1 ^ xd[1]);

		for(int i = 3; i <= n; ++i) {
			interact(i - 1, i, t, x);
			while(abs(x) % 2 != i % 2) {
				flip(i - 1, n);
				interact(i - 1, i, t, x);
			}
			flip(1, i);
			for(int j = 1; j < i; ++j) {
				if(rez[j] ^ xd[j])
					--x;
				else
					++x;
			}

			if(x == 1)
				rez[i] = (xd[i] ^ 1);
			else
				rez[i] = xd[i];
		}
	}
}

void finishPr(int n) {
	printf("! ");
	for(int i = 1; i <= n; ++i)
		fputc('0' + rez[i], stdout);
	fflush(stdout);
}

int main() {
#ifdef HOME
	FILE *fin = fopen("input.in", "r");
	FILE *fout = fopen("output.out", "w");
#else
	FILE *fin = stdin;
	FILE *fout = stdout;
#endif

	int n, t;
	scanf("%d%d", &n, &t);
	if(n % 2 == 0)
		evenCase(n, t);
	else if(n > 1)
		oddCase(n, t);
	else
		rez[1] = t;

	finishPr(n);

#ifdef HOME
	fclose(fin);
	fclose(fout);
#endif
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

const int MAX_N = 300;
bool xd[1+MAX_N];
bool rez[1+MAX_N];

void flip(int l, int r) {
	for(int i = l; i <= r; ++i)
		xd[i] ^= 1;
}

void interact(int l, int r, int &t, int &raise) {
	int t2;
	printf("? %d %d\n", l, r);
	fflush(stdout);
	scanf("%d", &t2);
	raise = t2 - t;
	t = t2;
	assert(t2 != -1);
}

void evenCase(int n, int t) {
	for(int i = 1; i <= n; ++i) {
		int x;
		interact(i, i, t, x);
		while(abs(x) % 2 != i % 2) { //flipped the bad side
			flip(i, n);
			interact(i, i, t, x);
		}
		if(abs(x) % 2 == i % 2) { // flipped my side
			flip(1, i);
			for(int j = 1; j < i; ++j) {
				if(rez[j] ^ xd[j])
					--x;
				else
					++x;
			}

			if(x == 1)
				rez[i] = (xd[i] ^ 1);
			else
				rez[i] = xd[i];
		}
	}
}

void oddCase(int n, int t) {
	int x, ti = t;
	interact(1, 2, t, x);
	while(x % 2 != 0) {
		flip(1, n);
		interact(1, 2, t, x);
	}
	flip(1, 2);
	if(x == 0) {
		while(1);
		if(x == 2)
			rez[1] = rez[2] = 0;
		else
			rez[1] = rez[2] = 1;

		for(int i = 3; i <= n; ++i) {
			interact(i - 1, i, t, x);
			while(abs(x) % 2 != i % 2) {
				flip(i - 1, n);
				interact(i - 1, i, t, x);
			}
			flip(1, i);
			for(int j = 3; j < i; ++j) {
				if(rez[j] ^ xd[j])
					--x;
				else
					++x;
			}

			if(x == 1)
				rez[i] = (xd[i] ^ 1);
			else
				rez[i] = xd[i];
		}

		interact(2, 3, t, x);
		while(abs(x) % 2 != 0) {
			flip(1, 3);
			interact(2, 3, t, x);
		}
		flip(2, n);
		for(int j = 3; j <= n; ++j)
			if(rez[j] ^ xd[j])
				--x;
			else
				++x;
		if(x == 1)
			rez[2] = (xd[2] ^ 1);
		else
			rez[2] = xd[2];
		rez[1] = (1 ^ rez[2]);

	} else {
		assert(false);
		if(x == 2)
			rez[1] = rez[2] = 0;
		else
			rez[1] = rez[2] = 1;

		for(int i = 3; i <= n; ++i) {
			interact(i - 1, i, t, x);
			while(abs(x) % 2 != i % 2) {
				flip(i - 1, n);
				interact(i - 1, i, t, x);
			}
			flip(1, i);
			for(int j = 1; j < i; ++j) {
				if(rez[j] ^ xd[j])
					--x;
				else
					++x;
			}

			if(x == 1)
				rez[i] = (xd[i] ^ 1);
			else
				rez[i] = xd[i];
		}
	}
}

void finishPr(int n) {
	printf("! ");
	for(int i = 1; i <= n; ++i)
		fputc('0' + rez[i], stdout);
	fflush(stdout);
}

int main() {
#ifdef HOME
	FILE *fin = fopen("input.in", "r");
	FILE *fout = fopen("output.out", "w");
#else
	FILE *fin = stdin;
	FILE *fout = stdout;
#endif

	int n, t;
	scanf("%d%d", &n, &t);
	if(n % 2 == 0)
		evenCase(n, t);
	else if(n > 1)
		oddCase(n, t);
	else
		rez[1] = t;

	finishPr(n);

#ifdef HOME
	fclose(fin);
	fclose(fout);
#endif
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

const int MAX_N = 300;
bool xd[1+MAX_N];
bool rez[1+MAX_N];

void flip(int l, int r) {
	for(int i = l; i <= r; ++i)
		xd[i] ^= 1;
}

void interact(int l, int r, int &t, int &raise) {
	int t2;
	printf("? %d %d\n", l, r);
	fflush(stdout);
	scanf("%d", &t2);
	raise = t2 - t;
	t = t2;
	assert(t2 != -1);
}

void evenCase(int n, int t) {
	for(int i = 1; i <= n; ++i) {
		int x;
		interact(i, i, t, x);
		while(abs(x) % 2 != i % 2) { //flipped the bad side
			flip(i, n);
			interact(i, i, t, x);
		}
		if(abs(x) % 2 == i % 2) { // flipped my side
			flip(1, i);
			for(int j = 1; j < i; ++j) {
				if(rez[j] ^ xd[j])
					--x;
				else
					++x;
			}

			if(x == 1)
				rez[i] = (xd[i] ^ 1);
			else
				rez[i] = xd[i];
		}
	}
}

void oddCase(int n, int t) {
	int x, ti = t;
	interact(1, 2, t, x);
	while(x % 2 != 0) {
		flip(1, n);
		interact(1, 2, t, x);
	}
	flip(1, 2);
	if(x == 0) {
    interact(2, 3, t, x);
    while(x % 2 != 0) {
      flip(1, 3);
      interact(2, 3, t, x);
    }
    flip(2, n);

    interact(1, 2, t, x);
    while(x % 2 != 0) {
      flip(1, n);
      interact(1, 2, t, x);
    }
    flip(1, 2);

    if(x == 2) {
      rez[1] = (1 ^ xd[1]);
      rez[2] = (1 ^ xd[2]);
    } else {
      rez[1] = xd[1];
      rez[2] = xd[2];
    }
	} else if(x == 2)
    rez[1] = rez[2] = (1 ^ xd[1]);
  else
    rez[1] = rez[2] = (0 ^ xd[1]);

  for(int i = 3; i <= n; ++i) {
    interact(i - 1, i, t, x);
    while(abs(x) % 2 != i % 2) {
      flip(i - 1, n);
      interact(i - 1, i, t, x);
    }
    flip(1, i);
    for(int j = 1; j < i; ++j) {
      if(rez[j] ^ xd[j])
        --x;
      else
        ++x;
    }

    if(x == 1)
      rez[i] = (xd[i] ^ 1);
    else
      rez[i] = xd[i];
  }
}

void finishPr(int n) {
	printf("! ");
	for(int i = 1; i <= n; ++i)
		fputc('0' + rez[i], stdout);
	fflush(stdout);
}

int main() {
#ifdef HOME
	FILE *fin = fopen("input.in", "r");
	FILE *fout = fopen("output.out", "w");
#else
	FILE *fin = stdin;
	FILE *fout = stdout;
#endif

	int n, t;
	scanf("%d%d", &n, &t);
	if(n % 2 == 0)
		evenCase(n, t);
	else if(n > 1)
		oddCase(n, t);
	else
		rez[1] = t;

	finishPr(n);

#ifdef HOME
	fclose(fin);
	fclose(fout);
#endif
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

const int MAX_N = 300;
bool xd[1+MAX_N];
bool rez[1+MAX_N];

void flip(int l, int r) {
	for(int i = l; i <= r; ++i)
		xd[i] ^= 1;
}

void interact(int l, int r, int &t, int &raise) {
	int t2;
	printf("? %d %d\n", l, r);
	fflush(stdout);
	scanf("%d", &t2);
	raise = t2 - t;
	t = t2;
	assert(t2 != -1);
}

void evenCase(int n, int t) {
	for(int i = 1; i <= n; ++i) {
		int x;
		interact(i, i, t, x);
		while(abs(x) % 2 != i % 2) { //flipped the bad side
			flip(i, n);
			interact(i, i, t, x);
		}
		if(abs(x) % 2 == i % 2) { // flipped my side
			flip(1, i);
			for(int j = 1; j < i; ++j) {
				if(rez[j] ^ xd[j])
					--x;
				else
					++x;
			}

			if(x == 1)
				rez[i] = (xd[i] ^ 1);
			else
				rez[i] = xd[i];
		}
	}
}

void oddCase(int n, int t) {
	int x, ti = t;
	interact(1, 2, t, x);
	while(x % 2 != 0) {
		flip(1, n);
		interact(1, 2, t, x);
	}
	flip(1, 2);
	if(x == 0) {
		if(x == 2)
			rez[1] = rez[2] = 0;
		else
			rez[1] = rez[2] = 1;

		for(int i = 3; i <= n; ++i) {
			interact(i - 1, i, t, x);
			while(abs(x) % 2 != i % 2) {
				flip(i - 1, n);
				interact(i - 1, i, t, x);
			}
			flip(1, i);
			for(int j = 3; j < i; ++j) {
				if(rez[j] ^ xd[j])
					--x;
				else
					++x;
			}

			if(x == 1)
				rez[i] = (xd[i] ^ 1);
			else
				rez[i] = xd[i];
		}

		interact(2, 3, t, x);
		while(abs(x) % 2 != 0) {
			flip(1, 3);
			interact(2, 3, t, x);
		}
		flip(2, n);
		for(int j = 3; j <= n; ++j)
			if(rez[j] ^ xd[j])
				--x;
			else
				++x;
		if(x == 1)
			rez[2] = (xd[2] ^ 1);
		else
			rez[2] = xd[2];
		rez[1] = (1 ^ rez[2]);

	} else {
		if(x == 2)
			rez[1] = rez[2] = 0;
		else
			rez[1] = rez[2] = 1;

		for(int i = 3; i <= n; ++i) {
			interact(i - 1, i, t, x);
			while(abs(x) % 2 != i % 2) {
				flip(i - 1, n);
				interact(i - 1, i, t, x);
			}
			flip(1, i);
			for(int j = 1; j < i; ++j) {
				if(rez[j] ^ xd[j])
					--x;
				else
					++x;
			}

			if(x == 1)
				rez[i] = (xd[i] ^ 1);
			else
				rez[i] = xd[i];
		}
	}
}

void finishPr(int n) {
	printf("! ");
	for(int i = 1; i <= n; ++i)
		fputc('0' + rez[i], stdout);
	fflush(stdout);
}

int main() {
#ifdef HOME
	FILE *fin = fopen("input.in", "r");
	FILE *fout = fopen("output.out", "w");
#else
	FILE *fin = stdin;
	FILE *fout = stdout;
#endif

	int n, t;
	scanf("%d%d", &n, &t);
	if(n % 2 == 0)
		evenCase(n, t);
	else if(n > 1)
		oddCase(n, t);
	else
		rez[1] = t;

	finishPr(n);

#ifdef HOME
	fclose(fin);
	fclose(fout);
#endif
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

const int MAX_N = 300;
bool xd[1+MAX_N];
bool rez[1+MAX_N];

void flip(int l, int r) {
	for(int i = l; i <= r; ++i)
		xd[i] ^= 1;
}

void interact(int l, int r, int &t, int &raise) {
	int t2;
	printf("? %d %d\n", l, r);
	fflush(stdout);
	scanf("%d", &t2);
	raise = t2 - t;
	t = t2;
	assert(t2 != -1);
}

void evenCase(int n, int t) {
	for(int i = 1; i <= n; ++i) {
		int x;
		interact(i, i, t, x);
		while(abs(x) % 2 != i % 2) { //flipped the bad side
			flip(i, n);
			interact(i, i, t, x);
		}
		if(abs(x) % 2 == i % 2) { // flipped my side
			flip(1, i);
			for(int j = 1; j < i; ++j) {
				if(rez[j] ^ xd[j])
					--x;
				else
					++x;
			}

			if(x == 1)
				rez[i] = (xd[i] ^ 1);
			else
				rez[i] = xd[i];
		}
	}
}

void oddCase(int n, int t) {
	int x, ti = t;
	interact(1, 2, t, x);
	while(x % 2 != 0) {
		flip(1, n);
		interact(1, 2, t, x);
	}
	flip(1, 2);
	if(x == 0) {
		if(x == 2)
			rez[1] = rez[2] = 0;
		else
			rez[1] = rez[2] = 1;

		for(int i = 3; i <= n; ++i) {
			interact(i - 1, i, t, x);
			while(abs(x) % 2 != i % 2) {
				flip(i - 1, n);
				interact(i - 1, i, t, x);
			}
			flip(1, i);
			for(int j = 3; j < i; ++j) {
				if(rez[j] ^ xd[j])
					--x;
				else
					++x;
			}

			if(x == 1)
				rez[i] = (xd[i] ^ 1);
			else
				rez[i] = xd[i];
		}

		interact(2, 3, t, x);
		while(abs(x) % 2 != 0) {
			flip(1, 3);
			interact(2, 3, t, x);
		}
		flip(2, n);
		for(int j = 3; j <= n; ++j)
			if(rez[j] ^ xd[j])
				--x;
			else
				++x;
		if(x == 1)
			rez[2] = (xd[2] ^ 1);
		else
			rez[2] = xd[2];
		rez[1] = (1 ^ rez[2]);

	} else {
		if(x == 2)
			rez[1] = rez[2] = 0;
		else
			rez[1] = rez[2] = 1;

		for(int i = 3; i <= n; ++i) {
			interact(i - 1, i, t, x);
			while(abs(x) % 2 != i % 2) {
				flip(i - 1, n);
				interact(i - 1, i, t, x);
			}
			flip(1, i);
			for(int j = 1; j < i; ++j) {
				if(rez[j] ^ xd[j])
					--x;
				else
					++x;
			}

			if(x == 1)
				rez[i] = (xd[i] ^ 1);
			else
				rez[i] = xd[i];
		}
	}
}

void finishPr(int n) {
	printf("! ");
	for(int i = 1; i <= n; ++i)
		fputc('0' + rez[i], stdout);
	fflush(stdout);
}

int main() {
#ifdef HOME
	FILE *fin = fopen("input.in", "r");
	FILE *fout = fopen("output.out", "w");
#else
	FILE *fin = stdin;
	FILE *fout = stdout;
#endif

	int n, t;
	printf("%d\n", (-1) % 2);
	scanf("%d%d", &n, &t);
	if(n % 2 == 0)
		evenCase(n, t);
	else if(n > 1)
		oddCase(n, t);
	else
		rez[1] = t;

	finishPr(n);

#ifdef HOME
	fclose(fin);
	fclose(fout);
#endif
	return 0;
}


#include <cstdio>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <cstring>
#include <cmath>

using namespace std;

#define pb push_back
#define all(X) X.begin(), X.end()
#define ll long long

void go(vector<int>& ret, int u, int v, int t, int x, int y) {
  int n = ret.size();
  int p = u;
  int nx = p - x;
  int pp = n - 1 - v;
  int ny = pp - y;
  int isleft = -1;
  int l, r;
  if (v - u == 0) {
    ret[u] = t - x - y;
    return;
  }
  if (v - u == 1) {
    if (t == x + y) {
      ret[u] = ret[u + 1] = 0;
      return;
    } else if (t - x - y == 2) {
      ret[u] = ret[u + 1] = 1;
      return;
    } else {
      int e;
      l = 0;
      r = 1;
      printf("? %d %d\n", u + 1, u + 1);
      fflush(stdout);
      scanf("%d", &e);
      if ((e % 2) == ((t + ny - y) % 2)) {
        go(ret, u, v, e, x, ny);
        isleft = 0;
      } else {
        int na = e - t - nx + x;
        na = 1 - na;
        na /= 2;
        ret[u] = !na;
        isleft = 1;
      }
    }
  }

  if (isleft == -1) {
    int nt = n - t;
    l = 1, r = 0;
    int px = ((x - nx) % 2 + 2) % 2;
    int py = ((y - ny) % 2 + 2) % 2;

    if (px != py) {
      r = 1;
    }
    printf("? %d %d\n", u + 1 + l, v - r + 1);
    fflush(stdout);
    int e;
    scanf("%d", &e);
    int fa = e - (nt + x - nx - 1);
    if (r == 0) {
      if (fa % 2 != 0) {
        go(ret, u, v, e, nx, y);
        isleft = 1;
      } else {
        int a = (e - nt - x + nx + 1) / 2;
        ret[u] = a;
        go(ret, u + 1, v, e, x, ny);
        isleft = 0;
      }
    } else {
      if (fa % 2 == 0) {
        go(ret, u, v, e, x, ny);
        isleft = 0;
      } else {
        int c = (e - nt - y + ny + 1) / 2;
        ret[v] = c;
        go(ret, u, v - 1, e, nx, y);
        isleft = 1;
      }
    }
  }

  if (isleft == 0) {
    for (int j = u + l; j <= v; j++)
      ret[j] = !ret[j];
  } else if (isleft == 1) {
    for (int j = u; j <= v - r; j++)
      ret[j] = !ret[j];
  }
}

int main()
{
#ifdef DEBUG
  freopen("e.in", "r", stdin);
  freopen("e.out", "w", stdout);
#endif
  int n, t;
  scanf("%d %d", &n, &t);
  vector<int> ret(n);
  for (auto &e: ret) e = -1;

  go(ret, 0, n - 1, t, 0, 0);
  printf("! ");
  for (int i = 0; i < n; i++) printf("%d", ret[i]);
  printf("\n");
  fflush(stdout);

  return 0;
}


#include <cstdio>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <cstring>
#include <cmath>

using namespace std;

#define pb push_back
#define all(X) X.begin(), X.end()
#define ll long long

void go(vector<int>& ret, int u, int v, int t, int x, int y) {
  int n = ret.size();
  int p = u;
  int nx = p - x;
  int pp = n - 1 - v;
  int ny = pp - y;
  int isleft = -1;
  int l, r;
  if (v - u == 0) {
    ret[u] = t - x - y;
    return;
  }
  if (v - u == 1) {
    if (t == x + y) {
      ret[u] = ret[u + 1] = 0;
      return;
    } else if (t - x - y == 2) {
      ret[u] = ret[u + 1] = 1;
      return;
    } else {
      int e;
      l = 0;
      r = 1;
      printf("? %d %d\n", u + 1, u + 1);
      fflush(stdout);
      scanf("%d", &e);
      if ((e % 2) == ((t + ny - y) % 2)) {
        go(ret, u, v, e, x, ny);
        isleft = 0;
      } else {
        int na = e - t - nx + x;
        ret[u] = na;
        isleft = 1;
      }
    }
  }

  if (isleft == -1) {
    int nt = n - t;
    l = 1, r = 0;
    int px = ((x - nx) % 2 + 2) % 2;
    int py = ((y - ny) % 2 + 2) % 2;

    if (px != py) {
      r = 1;
    }
    printf("? %d %d\n", u + 1 + l, v - r + 1);
    fflush(stdout);
    int e;
    scanf("%d", &e);
    int fa = e - (nt + x - nx - 1);
    if (r == 0) {
      if (fa % 2 != 0) {
        go(ret, u, v, e, nx, y);
        isleft = 1;
      } else {
        int a = (e - nt - x + nx + 1) / 2;
        ret[u] = a;
        go(ret, u + 1, v, e, x, ny);
        isleft = 0;
      }
    } else {
      if (fa % 2 == 0) {
        go(ret, u, v, e, x, ny);
        isleft = 0;
      } else {
        int c = (e - nt - y + ny + 1) / 2;
        ret[v] = c;
        go(ret, u, v - 1, e, nx, y);
        isleft = 1;
      }
    }
  }

  if (isleft == 0) {
    for (int j = u + l; j <= v; j++)
      ret[j] = !ret[j];
  } else if (isleft == 1) {
    for (int j = u; j <= v - r; j++)
      ret[j] = !ret[j];
  }
}

int main()
{
#ifdef DEBUG
  freopen("e.in", "r", stdin);
  freopen("e.out", "w", stdout);
#endif
  int n, t;
  scanf("%d %d", &n, &t);
  vector<int> ret(n);
  for (auto &e: ret) e = -1;

  go(ret, 0, n - 1, t, 0, 0);
  printf("! ");
  for (int i = 0; i < n; i++) printf("%d", ret[i]);
  printf("\n");
  fflush(stdout);

  return 0;
}


#include <cstdio>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <cstring>
#include <cmath>

using namespace std;

#define pb push_back
#define all(X) X.begin(), X.end()
#define ll long long

void go(vector<int>& ret, int u, int v, int t, int x, int y) {
  int n = ret.size();
  int p = u;
  int nx = p - x;
  int pp = n - 1 - v;
  int ny = pp - y;
  int isleft = -1;
  int l, r;
  if (v - u == 0) {
    ret[u] = t - x - y;
    return;
  }
  if (v - u == 1) {
    if (t == x + y) {
      ret[u] = ret[u + 1] = 0;
      return;
    } else if (t - x - y == 2) {
      ret[u] = ret[u + 1] = 1;
      return;
    } else {
      int e;
      l = 0;
      r = 1;
      printf("? %d %d\n", u + 1, u + 1);
      fflush(stdout);
      scanf("%d", &e);
      if ((e % 2) == ((t + ny - y) % 2)) {
        go(ret, u, v, e, x, ny);
        isleft = 0;
      } else {
        int na = e - t - nx + x;
        na = 1 - na;
        na /= 2;
        ret[u] = !na;
        ret[u + 1] = !na;
        isleft = 1;
      }
    }
  }

  if (isleft == -1) {
    int nt = n - t;
    l = 1, r = 0;
    int px = ((x - nx) % 2 + 2) % 2;
    int py = ((y - ny) % 2 + 2) % 2;

    if (px != py) {
      r = 1;
    }
    printf("? %d %d\n", u + 1 + l, v - r + 1);
    fflush(stdout);
    int e;
    scanf("%d", &e);
    int fa = e - (nt + x - nx - 1);
    if (r == 0) {
      if (fa % 2 != 0) {
        go(ret, u, v, e, nx, y);
        isleft = 1;
      } else {
        int a = (e - nt - x + nx + 1) / 2;
        ret[u] = a;
        go(ret, u + 1, v, e, x, ny);
        isleft = 0;
      }
    } else {
      if (fa % 2 == 0) {
        go(ret, u, v, e, x, ny);
        isleft = 0;
      } else {
        int c = (e - nt - y + ny + 1) / 2;
        ret[v] = c;
        go(ret, u, v - 1, e, nx, y);
        isleft = 1;
      }
    }
  }

  if (isleft == 0) {
    for (int j = u + l; j <= v; j++)
      ret[j] = !ret[j];
  } else if (isleft == 1) {
    for (int j = u; j <= v - r; j++)
      ret[j] = !ret[j];
  }
}

int main()
{
#ifdef DEBUG
  freopen("e.in", "r", stdin);
  freopen("e.out", "w", stdout);
#endif
  int n, t;
  scanf("%d %d", &n, &t);
  vector<int> ret(n);
  for (auto &e: ret) e = -1;

  go(ret, 0, n - 1, t, 0, 0);
  printf("! ");
  for (int i = 0; i < n; i++) printf("%d", ret[i]);
  printf("\n");
  fflush(stdout);

  return 0;
}


#include <cstdio>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <cstring>
#include <cmath>

using namespace std;

#define pb push_back
#define all(X) X.begin(), X.end()
#define ll long long

void go(vector<int>& ret, int n, int u, int t, int x) {
  int nx = u - x;
  int nt = n - t;
  if (u == n - 1) {
    ret[u] = t - x;
    return;
  }
  int l;
  if (u == n - 2) {
    if (t - x == 0) {
      ret[u] = ret[u + 1] = 0;
      return;
    } else if (t - x == 2) {
      ret[u] = ret[u + 1] = 1;
      return;
    } else {
      int nr = 0;
      while (true) {
        l = u;
        if ((t - nt) % 2 != 0) {
          l = u - 1;
        }
        printf("? %d %d\n", l + 1, u + 1);
        fflush(stdout);
        int e;
        scanf("%d", &e);
        int exp = l == u ? t % 2 : !(t % 2);
        if (e % 2 == exp) {
          t = e;
          nt = n - t;
          nr++;
          continue;
        }
        int b = e - nt + 1;
        b /= 2;
        ret[u + 1] = b;
        ret[u] = !b;
        break;
      }
      while(nr > 0) {
        for (int i = l; i < n; i++) ret[i] = !ret[i];
        nr--;
      }
      return;
    }
  }

  int nr = 0;
  int r;
  while (true) {
    l = 1;
    r = 0;
    int exp = nt % 2;
    //nt
    //nt + x - nx + a - na = nt + x - nx + 2a - 1
    if (abs(x - nx) % 2 == 1) {
      r = 1;
      exp = !exp;
    }
    printf("? %d %d\n", u + l + 1, n - r);
    fflush(stdout);
    int e;
    scanf("%d", &e);
    if (e % 2 == exp) {
      t = e;
      nt = n - t;
      swap(x, nx);
      nr++;
      continue;
    }
    int a = e - nt - x + nx + 1;
    a /= 2;
    ret[u] = a;
    t = e;
    break;
  }
  go(ret, n, u + 1, t, x + ret[u]);
  for (int i = u + l; i < n; i++) ret[i] = !ret[i];
  while (nr > 0) {
    for (int i = u; i < n - r; i++) ret[i] = !ret[i];
    nr--;
  }
}

int main()
{
#ifdef DEBUG
  freopen("e.in", "r", stdin);
  freopen("e.out", "w", stdout);
#endif
  int n, t;
  scanf("%d %d", &n, &t);
  vector<int> ret(n);
  go(ret, n, 0, t, 0);
  printf("! ");
  for (int i = 0; i < n; i++) printf("%d", ret[i]);
  printf("\n");
  fflush(stdout);

  return 0;
}


#include <cstdio>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <cstring>
#include <cmath>

using namespace std;

#define pb push_back
#define all(X) X.begin(), X.end()
#define ll long long

void go(vector<int>& ret, int n, int u, int t, int x) {
  int nx = u - x;
  int nt = n - t;
  if (u == n - 1) {
    ret[u] = t - x;
    return;
  }
  int l;
  if (u == n - 2) {
    if (t - x == 0) {
      ret[u] = ret[u + 1] = 0;
      return;
    } else if (t - x == 2) {
      ret[u] = ret[u + 1] = 1;
      return;
    } else {
      int nr = 0;
      while (true) {
        l = u;
        if ((t - nt) % 2 != 0) {
          l = u - 1;
        }
        printf("? %d %d\n", l + 1, u + 1);
        fflush(stdout);
        int e;
        scanf("%d", &e);
        int exp = l == u ? t % 2 : !(t % 2);
        if (e % 2 == exp) {
          t = e;
          nt = n - t;
          nr++;
          continue;
        }
        int b = e - nt + 1;
        b /= 2;
        ret[u + 1] = b;
        ret[u] = !b;
        break;
      }
      while(nr > 0) {
        for (int i = u; i < n; i++) ret[i] = !ret[i];
        nr--;
      }
      return;
    }
  }

  int nr = 0;
  int r;
  while (true) {
    l = 1;
    r = 0;
    int exp = nt % 2;
    //nt
    //nt + x - nx + a - na = nt + x - nx + 2a - 1
    if (abs(x - nx) == 1) {
      r = 1;
      exp = !exp;
    }
    printf("? %d %d\n", u + l + 1, n - r);
    fflush(stdout);
    int e;
    scanf("%d", &e);
    if (e % 2 == exp) {
      t = e;
      nt = n - t;
      swap(x, nx);
      nr++;
      continue;
    }
    int a = e - nt - x + nx + 1;
    a /= 2;
    ret[u] = a;
    t = e;
    break;
  }
  go(ret, n, u + 1, t, x + ret[u]);
  for (int i = u + l; i < n; i++) ret[i] = !ret[i];
  while (nr > 0) {
    for (int i = u; i < n - r; i++) ret[i] = !ret[i];
    nr--;
  }
}

int main()
{
#ifdef DEBUG
  freopen("e.in", "r", stdin);
  freopen("e.out", "w", stdout);
#endif
  int n, t;
  scanf("%d %d", &n, &t);
  vector<int> ret(n);
  go(ret, n, 0, t, 0);
  printf("! ");
  for (int i = 0; i < n; i++) printf("%d", ret[i]);
  printf("\n");
  fflush(stdout);

  return 0;
}


#include <cstdio>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <cstring>
#include <cmath>

using namespace std;

#define pb push_back
#define all(X) X.begin(), X.end()
#define ll long long

void go(vector<int>& ret, int n, int u, int t, int x) {
  int nx = u - x;
  int nt = n - t;
  if (u == n - 1) {
    ret[u] = t - x;
    return;
  }
  int l;
  if (u == n - 2) {
    if (t - x == 0) {
      ret[u] = ret[u + 1] = 0;
      return;
    } else if (t - x == 2) {
      ret[u] = ret[u + 1] = 1;
      return;
    } else {
      int nr = 0;
      while (true) {
        l = u;
        if ((t - nt) % 2 != 0) {
          l = u - 1;
        }
        printf("? %d %d\n", l + 1, u + 1);
        fflush(stdout);
        int e;
        scanf("%d", &e);
        int exp = l == u ? t % 2 : !(t % 2);
        if (e % 2 == exp) {
          t = e;
          nt = n - t;
          nr++;
          continue;
        }
        int b = e - nt + 1;
        b /= 2;
        ret[u + 1] = b;
        ret[u] = !b;
        break;
      }
      while(nr > 0) {
        for (int i = l; i < n; i++) ret[i] = !ret[i];
        nr--;
      }
      return;
    }
  }

  int nr = 0;
  int r;
  while (true) {
    l = 1;
    r = 0;
    int exp = nt % 2;
    //nt
    //nt + x - nx + a - na = nt + x - nx + 2a - 1
    if (abs(x - nx) == 1) {
      r = 1;
      exp = !exp;
    }
    printf("? %d %d\n", u + l + 1, n - r);
    fflush(stdout);
    int e;
    scanf("%d", &e);
    if (e % 2 == exp) {
      t = e;
      swap(x, nx);
      nr++;
      continue;
    }
    int a = e - nt - x + nx + 1;
    a /= 2;
    ret[u] = a;
    t = e;
    break;
  }
  go(ret, n, u + 1, t, x + ret[u]);
  for (int i = u + l; i < n; i++) ret[i] = !ret[i];
  while (nr > 0) {
    for (int i = u; i < n - r; i++) ret[i] = !ret[i];
    nr--;
  }
}

int main()
{
#ifdef DEBUG
  freopen("e.in", "r", stdin);
  freopen("e.out", "w", stdout);
#endif
  int n, t;
  scanf("%d %d", &n, &t);
  vector<int> ret(n);
  go(ret, n, 0, t, 0);
  printf("! ");
  for (int i = 0; i < n; i++) printf("%d", ret[i]);
  printf("\n");
  fflush(stdout);

  return 0;
}


#include <cstdio>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <cstring>
#include <cmath>

using namespace std;

#define pb push_back
#define all(X) X.begin(), X.end()
#define ll long long

void go(vector<int>& ret, int n, int u, int t, int x) {
  int nx = u - x;
  int nt = n - t;
  if (u == n - 1) {
    ret[u] = t - x;
    return;
  }
  int l;
  if (u == n - 2) {
    if (t - x == 0) {
      ret[u] = ret[u + 1] = 0;
      return;
    } else if (t - x == 2) {
      ret[u] = ret[u + 1] = 1;
      return;
    } else {
      int nr = 0;
      while (true) {
        l = u;
        if ((t - nt) % 2 != 0) {
          l = u - 1;
        }
        printf("? %d %d\n", l + 1, u + 1);
        fflush(stdout);
        int e;
        scanf("%d", &e);
        int exp = l == u ? t % 2 : !(t % 2);
        if (e % 2 == exp) {
          t = e;
          nt = n - t;
          nr++;
          continue;
        }
        int b = e - nt + 1;
        b /= 2;
        ret[u + 1] = b;
        ret[u] = !b;
        break;
      }
      while(nr > 0) {
        for (int i = l; i < n; i++) ret[i] = !ret[i];
        nr--;
      }
      return;
    }
  }

  int nr = 0;
  int r;
  while (true) {
    l = 1;
    r = 0;
    int exp = nt % 2;
    //nt
    //nt + x - nx + a - na = nt + x - nx + 2a - 1
    if (abs(x - nx) == 1) {
      r = 1;
      exp = !exp;
    }
    printf("? %d %d\n", u + l + 1, n - r);
    int e;
    scanf("%d", &e);
    if (e % 2 == exp) {
      t = e;
      swap(x, nx);
      nr++;
      continue;
    }
    int a = e - nt - x + nx + 1;
    a /= 2;
    ret[u] = a;
    t = e;
    break;
  }
  go(ret, n, u + 1, t, x + ret[u]);
  for (int i = u + l; i < n; i++) ret[i] = !ret[i];
  while (nr > 0) {
    for (int i = u; i < n - r; i++) ret[i] = !ret[i];
    nr--;
  }
}

int main()
{
#ifdef DEBUG
  freopen("e.in", "r", stdin);
  freopen("e.out", "w", stdout);
#endif
  int n, t;
  scanf("%d %d", &n, &t);
  vector<int> ret(n);
  go(ret, n, 0, t, 0);
  printf("! ");
  for (int i = 0; i < n; i++) printf("%d", ret[i]);
  printf("\n");
  fflush(stdout);

  return 0;
}


#include <cstdio>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <cstring>
#include <cmath>

using namespace std;

#define pb push_back
#define all(X) X.begin(), X.end()
#define ll long long

void go(vector<int>& ret, int n, int u, int t, int x) {
  int nx = u - x;
  int nt = n - t;
  if (u == n - 1) {
    ret[u] = t - x;
    return;
  }
  int l;
  if (u == n - 2) {
    if (t - x == 0) {
      ret[u] = ret[u + 1] = 0;
      return;
    } else if (t - x == 2) {
      ret[u] = ret[u + 1] = 1;
      return;
    } else {
      int nr = 0;
      while (true) {
        l = u;
        if ((t - nt) % 2 != 0) {
          l = u - 1;
        }
        printf("? %d %d\n", l + 1, u + 1);
        fflush(stdout);
        int e;
        scanf("%d", &e);
        int exp = l == u ? t % 2 : !(t % 2);
        if (e % 2 == exp) {
          t = e;
          nt = n - t;
          nr++;
          continue;
        }
        // nt + 2b - 1
        int b = e - nt + 1;
        b /= 2;
        ret[u + 1] = b;
        ret[u] = !b;
        break;
      }
      while(nr > 0) {
        for (int i = u; i < n; i++) ret[i] = !ret[i];
        nr--;
      }
      return;
    }
  }

  int nr = 0;
  int r;
  while (true) {
    l = 1;
    r = 0;
    int exp = nt % 2;
    //nt
    //nt + x - nx + a - na = nt + x - nx + 2a - 1
    //nt + 2b - 1
    //nt + x - nx + 2a - 1
    if (abs(x - nx) % 2 == 1) {
      r = 1;
      exp = !exp;
    }
    printf("? %d %d\n", u + l + 1, n - r);
    fflush(stdout);
    int e;
    scanf("%d", &e);
    if (e % 2 == exp) {
      t = e;
      nt = n - t;
      swap(x, nx);
      nr++;
      continue;
    }
    int a = e - nt - x + nx + 1;
    a /= 2;
    ret[u] = a;
    t = e;
    break;
  }
  go(ret, n, u + 1, t, x + ret[u]);
  for (int i = u + l; i < n; i++) ret[i] = !ret[i];
  while (nr > 0) {
    for (int i = u; i < n - r; i++) ret[i] = !ret[i];
    nr--;
  }
}

int main()
{
#ifdef DEBUG
  freopen("e.in", "r", stdin);
  freopen("e.out", "w", stdout);
#endif
  int n, t;
  scanf("%d %d", &n, &t);
  vector<int> ret(n);
  go(ret, n, 0, t, 0);
  printf("! ");
  for (int i = 0; i < n; i++) printf("%d", ret[i]);
  printf("\n");
  fflush(stdout);

  return 0;
}


#include <cstdio>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <cstring>
#include <cmath>

using namespace std;

#define pb push_back
#define all(X) X.begin(), X.end()
#define ll long long

void go(vector<int>& ret, int n, int u, int t, int x) {
  int nx = u - x;
  int nt = n - t;
  if (u == n - 1) {
    ret[u] = t - x;
    return;
  }
  int l;
  if (u == n - 2) {
    if (t - x == 0) {
      ret[u] = ret[u + 1] = 0;
      return;
    } else if (t - x == 2) {
      ret[u] = ret[u + 1] = 1;
      return;
    } else {
      int nr = 0;
      while (true) {
        l = u;
        if ((t - nt) % 2 != 0) {
          l = u - 1;
        }
        printf("? %d %d\n", l + 1, u + 1);
        fflush(stdout);
        int e;
        scanf("%d", &e);
        int exp = l == u ? t % 2 : !(t % 2);
        if (e % 2 == exp) {
          t = e;
          nt = n - t;
          nr++;
          continue;
        }
        int b = e - nt + 1;
        b /= 2;
        ret[u + 1] = b;
        ret[u] = !b;
        break;
      }
      while(nr > 0) {
        for (int i = l; i < n; i++) ret[i] = !ret[i];
        nr--;
      }
      return;
    }
  }

  int nr = 0;
  int r;
  while (true) {
    l = 1;
    r = 0;
    int exp = nt % 2;
    //nt
    //nt + x - nx + a - na = nt + x - nx + 2a - 1
    if (abs(x - nx) == 1) {
      r = 1;
      exp = !exp;
    }
    printf("? %d %d\n", u + l + 1, n - r);
    fflush(stdout);
    int e;
    scanf("%d", &e);
    if (e % 2 == exp) {
      t = e;
      nt = n - t;
      swap(x, nx);
      nr++;
      continue;
    }
    int a = e - nt - x + nx + 1;
    a /= 2;
    ret[u] = a;
    t = e;
    break;
  }
  go(ret, n, u + 1, t, x + ret[u]);
  for (int i = u + l; i < n; i++) ret[i] = !ret[i];
  while (nr > 0) {
    for (int i = u; i < n - r; i++) ret[i] = !ret[i];
    nr--;
  }
}

int main()
{
#ifdef DEBUG
  freopen("e.in", "r", stdin);
  freopen("e.out", "w", stdout);
#endif
  int n, t;
  scanf("%d %d", &n, &t);
  vector<int> ret(n);
  go(ret, n, 0, t, 0);
  printf("! ");
  for (int i = 0; i < n; i++) printf("%d", ret[i]);
  printf("\n");
  fflush(stdout);

  return 0;
}


#define _USE_MATH_DEFINES
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;

template <typename T1, typename T2>
string print_iterable(T1 begin_iter, T2 end_iter, int counter) {
    bool done_something = false;
    stringstream res;
    res << "[";
    for (; begin_iter != end_iter and counter; ++begin_iter) {
        done_something = true;
        counter--;
        res << *begin_iter << ", ";
    }
    string str = res.str();
    if (done_something) {
        str.pop_back();
        str.pop_back();
    }
    str += "]";
    return str;
}

vector<int> SortIndex(int size, std::function<bool(int, int)> compare) {
    vector<int> ord(size);
    for (int i = 0; i < size; i++) ord[i] = i;
    sort(ord.begin(), ord.end(), compare);
    return ord;
}

template <typename T>
bool MinPlace(T& a, const T& b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}

template <typename T>
bool MaxPlace(T& a, const T& b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}

template <typename Container>
int SZ(const Container& S) { return S.size(); }

template <typename S, typename T>
ostream& operator <<(ostream& out, const pair<S, T>& p) {
    out << "{" << p.first << ", " << p.second << "}";
    return out;
}

template <typename T>
ostream& operator <<(ostream& out, const vector<T>& v) {
    out << "[";
    for (int i = 0; i < (int)v.size(); i++) {
        out << v[i];
        if (i != (int)v.size()-1) out << ", ";
    }
    out << "]";
    return out;
}

#if DEBUG && !ONLINE_JUDGE
    ifstream input_from_file("input.txt");
    #define cin input_from_file

    #define dbg_var(x) clog << #x  << ": " << x << endl;
    #define dbg_array(x, len) clog << #x << ": " << print_iterable(x, x+len, -1) << endl;
#else
    #define dbg_var(x)
    #define dbg_array(x, len)
#endif

///////////////////////////////////////////////////////////////////////////
//////////////////// DO NOT TOUCH BEFORE THIS LINE ////////////////////////
///////////////////////////////////////////////////////////////////////////

const int MAXN = 400;
int N;
int curr;

int X[MAXN];
int false_query(int l, int r) {
    if (rand()%2) {
        for (int i = 1; i <= r; i++) X[i] = 1-X[i];
    } else for (int i = l; i <= N; i++) X[i] = 1-X[i];
    int res = 0;
    for (int i = 1; i <= N; i++) res += X[i];
    return res;
}

int query(int l, int r) {
    assert(1 <= l and r <= N);
    assert(l <= r);
    cout << "? " << l << " " << r << endl;

    // return false_query(l, r);
    int ans;
    cin >> ans;
    assert(ans != -1);
    return ans;
}

pair<int,int> get_ans(int l, int r) {
    assert(1 <= l and r <= N);
    assert(l <= r);
    assert(r%2 != (N+1-l) % 2);
    int ll = 0, rr = 0;

    pair<int,int> ans = {-1, -1};
    while (ll%2 != 0 or rr%2 != 0 or (ll == 0 and rr == 0)) {
        int val = query(l, r);
        bool ch = curr%2 != val%2;
        if (ch == r%2) {
            rr++;
            if (ans.second == -1) ans = {1, (r-(val-curr))/2};
        } else {
            ll++;
            if (ans.second == -1) ans = {-1, (N+1-l-(val-curr))/2};
        }
        curr = val;
    }
    return ans;
}

int get_pref(int r) {
    assert(r >= 2);
    int l = -1;
    if (N % 2) l = r-1;
    else l = r;
    pair<int,int> pp = get_ans(l, r);
    while (pp.first != 1) pp = get_ans(l, r);
    return pp.second;
}

int get_suff(int l) {
    int r = -1;
    if (N % 2) r = l+1;
    else r = l;
    pair<int,int> pp = get_ans(l, r);
    while (pp.first != -1) pp = get_ans(l, r);
    return pp.second;
}

int main() {
    ios::sync_with_stdio(false);

    cin >> N >> curr;

    // TOREMOVE
    // curr = 0;
    // for (int i = 1; i <= N; i++) cin >> X[i], curr += X[i];
    // TOREMOVE

    if (N == 1) {
        cout << "! ";
        cout << curr << endl;
        return 0;
    }

    vector<int> pref(N+1);
    for (int i = 2; i <= N; i++) pref[i] = get_pref(i);
    int sum = curr;
    vector<int> ans(N+1);
    ans[1] = sum - get_suff(2);
    ans[2] = pref[2] - ans[1];
    for (int i = 3; i <= N; i++) ans[i] = pref[i] - pref[i-1];
    cout << "! ";
    for (int i = 1; i <= N; i++) cout << ans[i];
    cout << endl;
}


#include <bits/stdc++.h>
using namespace std;

const int N = 305;

int n, t, A[N], x, ans[N];

int Q(int l, int r) {
  cout << "? " <<  l <<" " << r << endl;
  fflush(stdout);
  cin >> x;
  return x;
}

int main() {
  cin >> n >> t;
  int last = 0;
  for(int i = n; i >= 1; -- i) {
    if(i != n) Q(i + 1, n);
    int x = Q(i, n);
    if(x - t == 1) ans[i] = 0;
    else ans[i] = 1;
    Q(i, n);
    if(i != n) Q(i + 1, n);
  }
  cout << "! ";
  for(int i = 1; i <= n; ++ i) putchar(ans[i] + '0');
}


#include <bits/stdc++.h>
using namespace std;

const int N = 305;

int n, t, A[N], x, ans[N], Rev[N], now;

int Q(int l, int r) {
  cout << "? " <<  l <<" " << r << endl;
  fflush(stdout);
  cin >> x;
  return x;
}

void rev(int l, int r) {
  for(int i = l; i <= r; ++ i) {
    if(ans[i] != -1) ans[i] = 1 - ans[i];
    Rev[i] ^= 1;
  }
}

int solve(int l, int r, bool who) {
  int L = 0;
  if(!who) L = n - l + 1; else L = r;
  while (1) {
    now = Q(l, r);
    bool mask = abs(now - t) & 1;
    if (mask == (n - l + 1) % 2) mask = 0;
    else mask = 1;
    if(!mask) rev(l, n); else rev(1, r);
    if(mask == who) {
      int ans =  (now - t + L) >> 1;
      return ans;
    }
    else t = now;
  }
  assert(2132);
  return 0;
}

int main() {
  cin >> n >> t;
  for(int i = 1; i <= n; ++ i) ans[i] = -1;
  if(n == 1) {
    cout << "! " << t << endl;
    return 0;
  }
  if(n & 1) {
    int res = solve(2, n, 0);
    ans[1] = now - res;
    t = now;
    for(int i = 1; i < n; ++ i) {
      int res = solve(i, i + 1, 1);
      int Sum = 0;
      for(int j = 1; j <= i; ++ j) Sum += ans[j];
      ans[i + 1] = res - Sum;
      t = now;
    }
  }
  else {
    for(int i = 1; i <= n; ++ i) {
      int res = solve(i, i, 1);
      int Sum = 0;
      for(int j = 1; j < i; ++ j) Sum += ans[j];
      ans[i] = res - Sum;
      t = now;
    }
  }
  cout << "! ";
  for(int i = 1; i <= n; ++ i)
    if(Rev[i]) printf("%d", 1 - ans[i]);
    else printf("%d", ans[i]);
}


#include <bits/stdc++.h>
using namespace std;

const int N = 305;

int n, t, A[N], x, ans[N], Rev[N], now;

int Q(int l, int r) {
  cout << "? " <<  l <<" " << r << endl;
  fflush(stdout);
  cin >> x;
  return x;
}

void rev(int l, int r) {
  for(int i = l; i <= r; ++ i) {
    if(ans[i] != -1) ans[i] = 1 - ans[i];
    Rev[i] ^= 1;
  }
}

int solve(int l, int r, bool who) {
  int L = 0;
  if(!who) L = n - l + 1; else L = r;
  while (1) {
    now = Q(l, r);
    bool mask = abs(now - t) & 1;
    if (mask == (n - l + 1) % 2) mask = 0;
    else mask = 1;
    if(!mask) rev(l, n); else rev(1, r);
    if(mask == who) {
      int ans =  (now - t + L) >> 1;
      return ans;
    }
    else t = now;
  }
  assert(2132);
  return 0;
}

int main() {
  cin >> n >> t;
  for(int i = 1; i <= n; ++ i) ans[i] = -1;
  if(n == 1) {
    cout << "! " << t << endl;
    return 0;
  }
  if(n & 1) {
    int res = solve(2, n, 0);
    ans[1] = t - res;
    t = now;
    for(int i = 1; i < n; ++ i) {
      int res = solve(i, i + 1, 1);
      int Sum = 0;
      for(int j = 1; j <= i; ++ j) Sum += ans[j];
      ans[i + 1] = res - Sum;
      t = now;
    }
  }
  else {
    for(int i = 1; i <= n; ++ i) {
      int res = solve(i, i, 1);
      int Sum = 0;
      for(int j = 1; j < i; ++ j) Sum += ans[j];
      ans[i] = res - Sum;
      t = now;
    }
  }
  cout << "! ";
  for(int i = 1; i <= n; ++ i)
    if(Rev[i]) printf("%d", 1 - ans[i]);
    else printf("%d", ans[i]);
}


#include <bits/stdc++.h>
using namespace std;

const int N = 305;

int n, t, A[N], x, ans[N];

int Q(int l, int r) {
  cout << "! " <<  l <<" " << r << endl;
  fflush(stdout);
  cin >> x;
  return x;
}

int main() {
  cin >> n >> t;
  int last = 0;
  for(int i = n; i >= 1; -- i) {
    if(i != n) Q(i + 1, n);
    int x = Q(i, n);
    if(x - t == 1) ans[i] = 0;
    else ans[i] = 1;
    Q(i, n);
    if(i != n) Q(i + 1, n);
  }
  cout << "! ";
  for(int i = 1; i <= n; ++ i) putchar(ans[i] + '0');
}


#include <algorithm>
#include <cassert>
#include <iostream>
#include <vector>
using namespace std;

int N, T;

int query(int L, int R) {
    cout << "? " << L << ' ' << R << endl;
    int t;
    cin >> t;

    if (t == -1)
        exit(0);

    T = t;
    return t;
}

int guaranteed_flip(int L, int R) {
    assert(R == N || R % 2 != N % 2);

    if (R == N)
        return query(L, R);

    int goal_parity_change = (R - L + 1) % 2;

    while (true) {
        int start_T = T;
        int result = query(L, R);

        if ((start_T + result) % 2 == goal_parity_change)
            return result;

        // We missed. Revert and try again.
        query(L, N);
    }
}

int main() {
    cin >> N >> T;
    vector<int> original(N + 1, -1);

    for (int i = N; i > 0; i--) {
        int start_T = T;

        if (i == N) {
            original[N] = guaranteed_flip(N, N) > start_T ? 0 : 1;
            guaranteed_flip(N, N);
            continue;
        }

        if ((N - i) % 2 != 0) {
            original[i] = guaranteed_flip(i, i) > start_T ? 0 : 1;
            guaranteed_flip(i, i);
        } else {
            // Tricky case.
            original[i] = guaranteed_flip(i, i + 1) + (original[i + 1] == 0 ? -1 : +1) > start_T ? 0 : 1;
            guaranteed_flip(i, i + 1);
        }
    }

    cout << "! ";

    for (int i = 1; i <= N; i++)
        cout << original[i];

    cout << endl;
}


#include <algorithm>
#include <cassert>
#include <iostream>
#include <vector>
using namespace std;

int N, T;

int query(int L, int R) {
    assert(1 <= L && L <= R && R <= N);
    cout << "? " << L << ' ' << R << endl;
    int t;
    cin >> t;

    if (t == -1)
        exit(0);

    T = t;
    return t;
}

int guaranteed_flip(int L, int R) {
    assert(R == N || R % 2 != N % 2);

    if (R == N)
        return query(L, R);

    int goal_parity_change = (R - L + 1) % 2;

    while (true) {
        int start_T = T;
        int result = query(L, R);

        if ((start_T + goal_parity_change) % 2 == result % 2)
            return result;

        // We missed. Revert and try again.
        query(L, N);
    }
}

int main() {
    cin >> N >> T;
    vector<int> original(N + 1, -1);

    for (int i = N; i > 0; i--) {
        int start_T = T;

        if (i == N) {
            original[N] = guaranteed_flip(N, N) > start_T ? 0 : 1;
            guaranteed_flip(N, N);
            continue;
        }

        if ((N - i) % 2 != 0) {
            original[i] = guaranteed_flip(i, i) > start_T ? 0 : 1;
            guaranteed_flip(i, i);
        } else {
            // Tricky case.
            original[i] = guaranteed_flip(i, i + 1) + (original[i + 1] == 0 ? -1 : +1) > start_T ? 0 : 1;
            guaranteed_flip(i, i + 1);
        }
    }

    cout << "! ";

    for (int i = 1; i <= N; i++)
        cout << original[i];

    cout << endl;
}


#include <algorithm>
#include <cassert>
#include <iostream>
#include <vector>
using namespace std;

int N, T;

int query(int L, int R) {
    assert(1 <= L && L <= R && R <= N);
    cout << "? " << L << ' ' << R << endl;
    int t;
    cin >> t;

    if (t == -1)
        exit(0);

    T = t;
    return t;
}

int guaranteed_flip(int L, int R, int which = 0, bool check = true) {
    if (check)
        assert(R % 2 != (N - L + 1) % 2);

    int goal_parity_change = R % 2;
    int left_flips = 0, right_flips = 0;

    while (true) {
        int start_T = T;
        int result = query(L, R);

        if ((start_T + goal_parity_change) % 2 == result % 2)
            left_flips++;
        else
            right_flips++;

        if (which == 0 && left_flips % 2 == 1 && right_flips % 2 == 0)
            return result;

        if (which == 1 && left_flips % 2 == 0 && right_flips % 2 == 1)
            return result;
    }
}

vector<int> original;

void output() {
    cout << "! ";

    for (int i = 1; i <= N; i++)
        cout << original[i];

    cout << endl;
}

void solve_original(int first_element, vector<bool> &same) {
    int current;

    for (int i = 1; i <= N; i++) {
        if (i == 1) {
            current = first_element;
        } else {
            current = same[i - 1] ? current : 1 - current;
        }

        original[i] = current;
    }
}

int main() {
    cin >> N >> T;

    if (N == 1) {
        original = {0, T};
        output();
        return 0;
    }

    original.assign(N + 1, -1);

    if (N % 2 == 0) {
        int running_count = 0;

        for (int i = 1; i <= N; i++) {
            int start_T = T;
            int left_flip_change = (i - 1) - 2 * running_count;
            original[i] = guaranteed_flip(i, i) > start_T + left_flip_change ? 0 : 1;
            running_count += original[i];
            guaranteed_flip(i, i);
        }

        output();
        return 0;
    }

    vector<int> saved_changes(N + 1, 0);
    vector<bool> same(N + 1, false);

    for (int i = 1; i < N; i += 2) {
        int expected_change = i == 1 ? 0 : saved_changes[i - 2];
        int start_T = T;
        saved_changes[i] = guaranteed_flip(i, i + 1) - start_T;
        same[i] = saved_changes[i] != expected_change;
        guaranteed_flip(i, i + 1);
    }

    for (int i = N - 1; i > 1; i -= 2) {
        int expected_change = i == N - 1 ? 0 : saved_changes[i + 2];
        int start_T = T;
        saved_changes[i] = guaranteed_flip(i, i + 1, 1) - start_T;
        same[i] = saved_changes[i] != expected_change;
        guaranteed_flip(i, i + 1, 1);
    }

    int same_as_first = 1;
    bool current = true;

    for (int i = 1; i < N; i++) {
        if (!same[i])
            current = !current;

        if (current)
            same_as_first++;
    }

    solve_original(same_as_first > N / 2 ^ T > N / 2 ? 0 : 1, same);
    output();
}


#include <unordered_set>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <vector>
#include <chrono>
#include <random>
#include <bitset>
#include <queue>
#include <cmath>
#include <set>
#include <map>
using namespace std;

int main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int n, t;
    cin >> n >> t;
    if(t==0){
        cout << "! ";
        for(int i = 0; i<n; i++)
            cout << '0';
        cout << endl;
        return 0;
    }
    if(t==n){
        cout << "! ";
        for(int i = 0; i<n; i++)
            cout << '1';
        cout << endl;
        return 0;
    }
    if(n&1){
        string ans = "";
        int lst = 0;
        int kek = 0;
        while(true){
            cout << "? " << 2 << ' ' << n << endl;
            int jij;
            cin >> jij;
            if(((t-jij)&1)!=(n&1)){
                jij = n-jij;
                ans.push_back('0'+((lst<(t-jij))^kek));
                t = n-t;
                lst = jij-t;
                jij = n-jij;
                t = jij;
                kek ^= 1;
                break;
            }
            else{
                kek ^= 1;
                t = jij;
                continue;
            }
        }
        for(int i = 1; i<n; i++){
            while(true){
                //cerr << i << ") " << t << ' ' << lst << ' ' << kek << endl;
                cout << "? " << i << ' ' << i+1 << endl;
                int jij;
                cin >> jij;
                if(((t-jij)&1)==((i+1)&1)){
                    ans.push_back('0'+((lst<(t-jij))^kek));
                    lst = jij-t;
                    t = jij;
                    break;
                }
                else{
                    if(kek^(ans.back()-'0'))
                        lst += 2;
                    else
                        lst -= 2;
                    kek ^= 1;
                    t = jij;
                    continue;
                }
            }
        }
        cout << "! " << ans << endl;
    }
    else{
        string ans = "";
        int lst = 0;
        int kek = 0;
        for(int i = 0; i<n; i++){
            //cerr << i << ") " << t << ' ' << lst << endl;
            while(true){
                cout << "? " << i+1 << ' ' << i+1 << endl;
                int jij;
                cin >> jij;
                if(((jij-t)&1)==(i&1)){
                    t = jij;
                    kek ^= 1;
                    continue;
                }
                else{
                    ans.push_back('0'+((lst<(t-jij))^kek));
                    lst = jij-t;
                    t = jij;
                    break;
                }
            }
        }
        cout << "! " << ans << endl;
    }

    return 0;
}


#include <unordered_set>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <vector>
#include <chrono>
#include <random>
#include <bitset>
#include <queue>
#include <cmath>
#include <set>
#include <map>
using namespace std;

int main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int n, t;
    cin >> n >> t;
    if(n&1){
        string ans = "";
        int lst = 0;
        int kek = 0;
        while(true){
            cout << "? " << 2 << ' ' << n << endl;
            int jij;
            cin >> jij;
            if(((t-jij)&1)!=(n&1)){
                jij = n-jij;
                ans.push_back('0'+((lst<(t-jij))^kek));
                t = n-t;
                lst = jij-t;
                jij = n-jij;
                t = jij;
                kek ^= 1;
                break;
            }
            else{
                kek ^= 1;
                t = jij;
                continue;
            }
        }
        for(int i = 1; i<n; i++){
            while(true){
                //cerr << i << ") " << t << ' ' << lst << ' ' << kek << endl;
                cout << "? " << i << ' ' << i+1 << endl;
                int jij;
                cin >> jij;
                if(((t-jij)&1)==((i+1)&1)){
                    ans.push_back('0'+((lst<(t-jij))^kek));
                    lst = jij-t;
                    t = jij;
                    break;
                }
                else{
                    if(kek)
                        lst -= 2;
                    else
                        lst += 2;
                    kek ^= 1;
                    t = jij;
                    continue;
                }
            }
        }
        cout << "! " << ans << endl;
    }
    else{
        string ans = "";
        int lst = 0;
        int kek = 0;
        for(int i = 0; i<n; i++){
            //cerr << i << ") " << t << ' ' << lst << endl;
            while(true){
                cout << "? " << i+1 << ' ' << i+1 << endl;
                int jij;
                cin >> jij;
                if(((jij-t)&1)==(i&1)){
                    t = jij;
                    kek ^= 1;
                    continue;
                }
                else{
                    ans.push_back('0'+((lst<(t-jij))^kek));
                    lst = jij-t;
                    t = jij;
                    break;
                }
            }
        }
        cout << "! " << ans << endl;
    }

    return 0;
}


#include <unordered_set>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <vector>
#include <chrono>
#include <random>
#include <bitset>
#include <queue>
#include <cmath>
#include <set>
#include <map>
using namespace std;

int main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int n, t;
    cin >> n >> t;
    if(t==0){
        cout << "! ";
        for(int i = 0; i<n; i++)
            cout << '0';
        cout << endl;
        return 0;
    }
    if(t==n){
        cout << "! ";
        for(int i = 0; i<n; i++)
            cout << '1';
        cout << endl;
        return 0;
    }
    if(n&1){
        string ans = "";
        int lst = 0;
        int kek = 0;
        while(true){
            cout << "? " << 2 << ' ' << n << endl;
            int jij;
            cin >> jij;
            if(((t-jij)&1)!=(n&1)){
                jij = n-jij;
                ans.push_back('0'+((lst<(t-jij))^kek));
                //t = n-t;
                lst = t-jij;
                jij = n-jij;
                t = jij;
                kek ^= 1;
                break;
            }
            else{
                kek ^= 1;
                t = jij;
                continue;
            }
        }
        for(int i = 1; i<n; i++){
            while(true){
                //cerr << i << ") " << t << ' ' << lst << ' ' << kek << endl;
                cout << "? " << i << ' ' << i+1 << endl;
                int jij;
                cin >> jij;
                if(((t-jij)&1)==((i+1)&1)){
                    ans.push_back('0'+((lst<(t-jij))^kek));
                    lst = jij-t;
                    t = jij;
                    break;
                }
                else{
                    if(kek^(ans.back()-'0'))
                        lst += 2;
                    else
                        lst -= 2;
                    kek ^= 1;
                    t = jij;
                    continue;
                }
            }
        }
        cout << "! " << ans << endl;
    }
    else{
        string ans = "";
        int lst = 0;
        int kek = 0;
        for(int i = 0; i<n; i++){
            //cerr << i << ") " << t << ' ' << lst << endl;
            while(true){
                cout << "? " << i+1 << ' ' << i+1 << endl;
                int jij;
                cin >> jij;
                if(((jij-t)&1)==(i&1)){
                    t = jij;
                    kek ^= 1;
                    continue;
                }
                else{
                    ans.push_back('0'+((lst<(t-jij))^kek));
                    lst = jij-t;
                    t = jij;
                    break;
                }
            }
        }
        cout << "! " << ans << endl;
    }

    return 0;
}


#include <unordered_set>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <vector>
#include <chrono>
#include <random>
#include <bitset>
#include <queue>
#include <cmath>
#include <set>
#include <map>
using namespace std;

int main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int n, t;
    cin >> n >> t;
    if(n&1){
        string ans = "";
        int lst = 0;
        int kek = 0;
        while(true){
            cout << "? " << 2 << ' ' << n << endl;
            int jij;
            cin >> jij;
            if(((t-jij)&1)!=(n&1)){
                jij = n-jij;
                ans.push_back('0'+((lst<(t-jij))^kek));
                t = n-t;
                lst = jij-t;
                jij = n-jij;
                t = jij;
                kek ^= 1;
                break;
            }
            else{
                kek ^= 1;
                t = jij;
                continue;
            }
        }
        for(int i = 1; i<n; i++){
            while(true){
                //cerr << i << ") " << t << ' ' << lst << ' ' << kek << endl;
                cout << "? " << i << ' ' << i+1 << endl;
                int jij;
                cin >> jij;
                if(((t-jij)&1)==((i+1)&1)){
                    ans.push_back('0'+((lst<(t-jij))^kek));
                    lst = jij-t;
                    t = jij;
                    break;
                }
                else{
                    if(kek^(ans.back()-'0'))
                        lst += 2;
                    else
                        lst -= 2;
                    kek ^= 1;
                    t = jij;
                    continue;
                }
            }
        }
        cout << "! " << ans << endl;
    }
    else{
        string ans = "";
        int lst = 0;
        int kek = 0;
        for(int i = 0; i<n; i++){
            //cerr << i << ") " << t << ' ' << lst << endl;
            while(true){
                cout << "? " << i+1 << ' ' << i+1 << endl;
                int jij;
                cin >> jij;
                if(((jij-t)&1)==(i&1)){
                    t = jij;
                    kek ^= 1;
                    continue;
                }
                else{
                    ans.push_back('0'+((lst<(t-jij))^kek));
                    lst = jij-t;
                    t = jij;
                    break;
                }
            }
        }
        cout << "! " << ans << endl;
    }

    return 0;
}


#include <unordered_set>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <vector>
#include <chrono>
#include <random>
#include <bitset>
#include <queue>
#include <cmath>
#include <set>
#include <map>
using namespace std;

int main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int n, t;
    cin >> n >> t;
    if(n&1){
        string ans = "";
        int lst = 0;
        int kek = 0;
        while(true){
            cout << "? " << 2 << ' ' << n << endl;
            int jij;
            cin >> jij;
            if(((t-jij)&1)!=(n&1)){
                jij = n-jij;
                ans.push_back('0'+((lst<(t-jij))^kek));
                t = n-t;
                lst = jij-t;
                jij = n-jij;
                t = jij;
                kek ^= 1;
                break;
            }
            else{
                kek ^= 1;
                t = jij;
                continue;
            }
        }
        for(int i = 1; i<n; i++){
            //cerr << i << ") " << t << ' ' << lst << ' ' << kek << endl;
            while(true){
                cout << "? " << i << ' ' << i+1 << endl;
                int jij;
                cin >> jij;
                if(((t-jij)&1)==((i+1)&1)){
                    ans.push_back('0'+((lst<(t-jij))^kek));
                    lst = jij-t;
                    t = jij;
                    break;
                }
                else{
                    kek ^= 1;
                    t = jij;
                    continue;
                }
            }
        }
        cout << "! " << ans << endl;
    }
    else{
        string ans = "";
        int lst = 0;
        int kek = 0;
        for(int i = 0; i<n; i++){
            //cerr << i << ") " << t << ' ' << lst << endl;
            while(true){
                cout << "? " << i+1 << ' ' << i+1 << endl;
                int jij;
                cin >> jij;
                if(((jij-t)&1)==(i&1)){
                    t = jij;
                    kek ^= 1;
                    continue;
                }
                else{
                    ans.push_back('0'+((lst<(t-jij))^kek));
                    lst = jij-t;
                    t = jij;
                    break;
                }
            }
        }
        cout << "! " << ans << endl;
    }

    return 0;
}


#include <unordered_set>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <vector>
#include <chrono>
#include <random>
#include <bitset>
#include <queue>
#include <cmath>
#include <set>
#include <map>
using namespace std;

int main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int n, t;
    cin >> n >> t;
    if(n&1){
        string ans = "";
        int lst = 0;
        while(true){
            cout << "? " << 2 << ' ' << n << endl;
            int jij;
            cin >> jij;
            if(((t-jij)&1)!=(n&1)){
                jij = n-jij;
                ans.push_back('0'+(lst<(t-jij)));
                lst = t-jij;
                break;
            }
        }
        for(int i = 1; i<n; i++){
            while(true){
                cout << "? " << i << ' ' << i+1 << endl;
                int jij;
                cin >> jij;
                if(((t-jij)&1)==((i+1)&1)){
                    ans.push_back('0'+(lst<(t-jij)));
                    lst = t-jij;
                    break;
                }
            }
        }
        cout << "! " << ans << endl;
    }
    else{
        string ans = "";
        int lst = 0;
        for(int i = 0; i<n; i++){
            while(true){
                cout << "? " << i+1 << ' ' << i+1 << endl;
                int jij;
                cin >> jij;
                if(((t-jij)&1)==((i+1)&1)){
                    ans.push_back('0'+(lst<(t-jij)));
                    lst = t-jij;
                    break;
                }
            }
        }
        cout << "! " << ans << endl;
    }

    return 0;
}


#include <unordered_set>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <vector>
#include <chrono>
#include <random>
#include <bitset>
#include <queue>
#include <cmath>
#include <set>
#include <map>
using namespace std;

int main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int n, t;
    cin >> n >> t;
    if(n&1){
        string ans = "";
        int lst = 0;
        while(true){
            cout << "? " << 2 << ' ' << n << endl;
            int jij;
            cin >> jij;
            if(((t-jij)&1)!=(n&1)){
                jij = n-jij;
                ans.push_back('0'+(lst<(t-jij)));
                lst = t-jij;
                break;
            }
        }
        for(int i = 1; i<n; i++){
            while(true){
                cout << "? " << i << ' ' << i+1 << endl;
                int jij;
                cin >> jij;
                if(((t-jij)&1)==((i+1)&1)){
                    ans.push_back('0'+(lst<(t-jij)));
                    lst = t-jij;
                    break;
                }
            }
        }
        cout << "! " << ans << endl;
    }
    else{
        string ans = "";
        int lst = 0;
        int kek = 0;
        for(int i = 0; i<n; i++){
            //cerr << i << ") " << t << ' ' << lst << endl;
            while(true){
                cout << "? " << i+1 << ' ' << i+1 << endl;
                int jij;
                cin >> jij;
                if(((jij-t)&1)==(i&1)){
                    t = jij;
                    kek ^= 1;
                    continue;
                }
                else{
                    ans.push_back('0'+((lst<(t-jij))^kek));
                    lst = jij-t;
                    t = jij;
                    break;
                }
            }
        }
        cout << "! " << ans << endl;
    }

    return 0;
}


#include <bits/stdc++.h>
#define FR first
#define SE second
#define last last2

using namespace std;

typedef pair<int,int> pr;

int n,m,lst;

char str[305];

int modify(int l,int r) {
  /*int v=rand()%2;
  if (!v) {
  	printf("0 ");
  	for(int i=1;i<=r;i++) str[i]=((str[i]=='1')?'0':'1');
  }
  else {
  	printf("1 ");
  	for(int i=l;i<=n;i++) str[i]=((str[i]=='1')?'0':'1');
  }
  puts(str+1);
  int s=0;
  for(int i=1;i<=n;i++) s+=str[i]-'0';
  return s;*/
  return 0;
}

pr query(int l,int r) {
  printf("? %d %d\n",l,r);
  fflush(stdout);
  int x=modify(l,r);
  scanf("%d",&x);
  if (!((lst^r^x)&1)) {
  	lst=x;
    return pr(x,0);
  }
  else {
  	lst=x;
    return pr(x,1);
  }
}

char ans[305];

void solve_even() {
  int last=0;
  for(int i=1;i<=n;i++) {
  	bool v1=0,v2=0;
  	int x;
  	while (v1!=1||v2!=0) {
  		pr t=query(i,i);
  		if (!t.SE) v1^=1; else v2^=1;
  		x=t.FR;
	  }
	x=((m-x+i)>>1);
	ans[i]=x-last+'0';
	last=x;
	while (v1!=0||v2!=0) {
		pr t=query(i,i);
		if (!t.SE) v1^=1; else v2^=1;
	}
  }
  printf("! %s\n",ans+1);
}

void solve_odd() {
  if (n==1) {
  	printf("! %d\n",m);
  	return;
  }
  int last=0,s=m;
  for(int i=2;i<=n;i++) {
  	bool v1=0,v2=0;
  	int x;
  	while (v1!=1||v2!=0) {
  		pr t=query(i-1,i);
  		if (!t.SE) v1^=1; else v2^=1;
  		x=t.FR;
	  }
	x=((m-x+i)>>1);
	if (i>2) ans[i]=x-last+'0',s-=x-last;
	last=x;
	while (v1!=0||v2!=0) {
		pr t=query(i-1,i);
		if (!t.SE) v1^=1; else v2^=1;
	}
  }
  bool v1=0,v2=0;
  int x;
  while (v1!=0||v2!=1) {
  	pr t=query(2,n);
  	if (!t.SE) v1^=1; else v2^=1;
  	x=t.FR;
  }
  x=((m-x+n-1)>>1);
  ans[1]=m-x+'0',s-=m-x;
  ans[2]=s+'0';
  printf("! %s\n",ans+1);
}

int main() {
  scanf("%d%d",&n,&m);
  //scanf("%s",str+1);
  lst=m;
  if (n&1) solve_odd();
  else solve_even();
  return 0;
}


#include <bits/stdc++.h>
using namespace std;
//using lint = long long;

struct P
{
    int x,y;

    bool operator<(const P &a)const{
        if(x!=a.x)
              return x>a.x;
        return y>a.y;
    }

};

vector<int> v;

//bitset<4001000> b;
int i,n,d,m,k,a,b,c,h;

int o[311];
int l[311];
int j[331];
int e;

//int dx[10]={2,2,-2,-2,1,1,-1,-1},dy[10]={1,-1,1,-1,2,-2,2,-2};

int dx[10]={0,1,0,-1,1,1,-1,-1},dy[10]={1,0,-1,0,1,-1,1,-1},dz[10]={0,0,0,0,1,-1};
long long mod=998244353,mod2=1000000009,mod3=2017;
long long x,z,y;
double pi=3.14159265;
P u[3];
stack<int> s;
//set<int> s[222][22];
//priority_queue<P> q;
queue<int> q;
//2147483647
//'1'==49;
//'A'==65;
//'a'==97;
//unordered_
//map<int,int> p;
/*
struct custom_hash {
    static uint64_t splitmix64(uint64_t x) {
        // http://xorshift.di.unimi.it/splitmix64.c
        x += 0x9e3779b97f4a7c15;
        x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
        x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
        return x ^ (x >> 31);
    }

    size_t operator()(uint64_t x) const {
        static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
        return splitmix64(x + FIXED_RANDOM);
    }
};
unordered_map<long long, int, custom_hash> safe_map;
*/
//list<int> l;
//srand((int)time(NULL));
string r;
//char r[222253];
//deque<int> de;

/*bool as(P a,P b)
{
    if(a.x!=b.x)
    return a.x<b.x;
    return a.y<b.y;
}*/

bool as(P a,P b)
{
    if(a.x!=b.x)
        return a.x<b.x;
    return a.y<b.y;
}

int f(int n,int m)
{
    /*if(u)
    for(int t=1;t<=n;t++)
        j[t]=1-j[t];
    else
        for(int t=m;t<=a;t++)
        j[t]=1-j[t];
    printf("%d %d %d\n",n,m,u);
    int q=0;
    for(int t=1;t<=a;t++)
    q+=j[t];
    return q;
*/
    printf("? %d %d\n",n,m);
    fflush(stdout);
    int p;
    scanf("%d",&p);
    return p;
}

void g1()
{
    //srand((int)time(NULL));
    n=b;
    for(int t=1;t<=a;t++)
    {
        for(;(c=f(t,t))&&(((n-c)%2+2)%2!=t%2);)
        {
            //puts("#");
            for(int w=t;w<=a;l[w]++,w++);
            n=c;
        }
        int x=n,y=c;
        for(int w=1;w<t;w++)
            if((l[w]+o[w])%2) x--;
            else y--;
        if((x>y&&l[t]%2==0)||(x<y&&l[t]%2)) o[t]=1;
        for(int w=1;w<=t;w++)
            l[w]++;
        n=c;
    }
}

void g2()
{
    if(a==1)
    {
        if(b) o[1]=1;
        return;
    }

    n=b;
    for(;(c=f(2,a-1))&&((n-c)%2+2)%2==0;)
    {
        for(int t=1;t<a;t++)
            l[t]++;
        n=c;
    }
    if((n>(a-c)&&l[1]%2==0)||(n<(a-c)&&l[1]%2)) o[1]=1;
    for(int t=2;t<=a;t++)
        l[t]++;
    n=c;
    for(int t=2;t<=a;t++)
    {
        for(;(c=f(t-1,t))&&(((n-c)%2+2)%2!=t%2);)
        {
            for(int w=t-1;w<=a;l[w]++,w++);
            n=c;
        }
        int x=n,y=c;
        for(int w=1;w<t;w++)
            if((l[w]+o[w])%2) x--;
            else y--;
        if(((x==y+1)&&(l[t]%2==0))||((x+1==y)&&(l[t]%2))) o[t]=1;
        for(int w=1;w<=t;w++)
            l[w]++;
        n=c;
    }

}

int main()
{
    cin>>r;
    for(int t=0;t<r.size();b+=j[t+1],t++)
        j[t+1]=r[t]-'0';
    a=r.size();
    //scanf("%d %d",&a,&b);
    if(a%2) g2();
    else g1();
    printf("! ");
    for(int t=1;t<=a;t++)
        printf("%d",o[t]);
    puts("");
    fflush(stdout);
}