Problem: cf1282_d
Difficulty: easy
Categories: data structures, math
Time limit: 1000 ms, memory limit: 256 MB

This is an interactive problem.

After completing the last level of the enchanted temple, you received a powerful artifact of the 255th level. Do not rush to celebrate, because this artifact has a powerful rune that can be destroyed with a single spell $s$, which you are going to find.

We define the spell as some non-empty string consisting only of the letters a and b.

At any time, you can cast an arbitrary non-empty spell $t$, and the rune on the artifact will begin to resist. Resistance of the rune is the edit distance between the strings that specify the casted spell $t$ and the rune-destroying spell $s$.

Edit distance of two strings $s$ and $t$ is a value equal to the minimum number of one-character operations of replacing, inserting and deleting characters in $s$ to get $t$. For example, the distance between ababa and aaa is $2$, the distance between aaa and aba is $1$, the distance between bbaba and abb is $3$. The edit distance is $0$ if and only if the strings are equal.

It is also worth considering that the artifact has a resistance limit  — if you cast more than $n + 2$ spells, where $n$ is the length of spell $s$, the rune will be blocked.

Thus, it takes $n + 2$ or fewer spells to destroy the rune that is on your artifact. Keep in mind that the required destructive spell $s$ must also be counted among these $n + 2$ spells.

Note that the length $n$ of the rune-destroying spell $s$ is not known to you in advance. It is only known that its length $n$ does not exceed $300$.

Interaction

Interaction is happening through queries.

Each request consists of a single non-empty string $t$  — the spell you want to cast. The length of string $t$ should not exceed $300$. Each string should consist only of the letters a and b.

In response to the query, you will get resistance runes  — the edit distance between the strings that specify the casted spell $t$ and the secret rune-destroying spell $s$. Remember that $s$ contains only the letters a and b.

After breaking the rune, your program should end immediately. A rune is destroyed when you get a response with resistance $0$. After receiving the value $0$, your program should terminate normally.

In this problem interactor is not adaptive. This means that during any test the rune-destroying spell $s$ does not change.

If your query is invalid, -1 will be returned. After receiving this your program should immediately terminate normally (for example, by calling exit(0)), otherwise, the testing system may issue an arbitrary verdict.

If the number of spells exceeds limit ($n + 2$, where $n$ is the length of the spell $s$, which is unknown to you), you will get the Wrong Answer verdict.

Your solution may receive the verdict Idleness Limit Exceeded if you don't output anything or forget to flush the output buffer.

To flush the output buffer, you need to do the following immediately after printing the query and the line end:

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

Example

Input

```
2

2

1

2

3

0
```

Output

```
aaa

aaab

abba

bba

abaaa

aabba
```

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

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

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

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

static bool isValidSpell(const string& t) {
    if (t.empty() || (int)t.size() > 300) return false;
    for (char c : t) if (c != 'a' && c != 'b') return false;
    return true;
}


struct MyersED {
    int m = 0;
    int blocks = 0;
    uint64_t lastMask = 0;
    vector<uint64_t> peqA, peqB;

    explicit MyersED(const string& pattern) {
        m = (int)pattern.size();
        blocks = (m + 63) / 64;
        lastMask = (m % 64 == 0) ? ~0ULL : ((1ULL << (m % 64)) - 1ULL);
        peqA.assign(blocks, 0);
        peqB.assign(blocks, 0);
        for (int i = 0; i < m; i++) {
            int b = i >> 6;
            int bit = i & 63;
            if (pattern[i] == 'a') peqA[b] |= (1ULL << bit);
            else peqB[b] |= (1ULL << bit);
        }
    }

    int distanceTo(const string& text) const {
        vector<uint64_t> Pv(blocks, ~0ULL), Mv(blocks, 0ULL);
        if (blocks > 0) {
            Pv[blocks - 1] |= ~lastMask; 
            Mv[blocks - 1] &= lastMask;
        }

        int score = m;
        const int lastBlock = blocks - 1;
        const uint64_t lastBit = 1ULL << ((m - 1) & 63);

        for (char ch : text) {
            const vector<uint64_t>& Peq = (ch == 'a') ? peqA : peqB;

            uint64_t carryAdd = 0;
            uint64_t carryPh = 0;
            uint64_t carryMh = 0;

            for (int b = 0; b < blocks; b++) {
                uint64_t Eq = Peq[b];
                uint64_t Pv_b = Pv[b];
                uint64_t Mv_b = Mv[b];

                uint64_t Xv = Eq | Mv_b;

                uint64_t temp = Eq & Pv_b;
                unsigned __int128 sum128 = (unsigned __int128)temp + (unsigned __int128)Pv_b + (unsigned __int128)carryAdd;
                uint64_t sum = (uint64_t)sum128;
                carryAdd = (uint64_t)(sum128 >> 64);

                uint64_t Xh = (sum ^ Pv_b) | Eq;
                uint64_t Ph = Mv_b | ~(Xh | Pv_b);
                uint64_t Mh = Pv_b & Xh;

                if (b == lastBlock) {
                    if (Ph & lastBit) score++;
                    else if (Mh & lastBit) score--;
                }

                uint64_t nextCarryPh = (Ph >> 63) & 1ULL;
                uint64_t nextCarryMh = (Mh >> 63) & 1ULL;

                uint64_t PhShift = (Ph << 1) | carryPh;
                if (b == 0) PhShift |= 1ULL;
                uint64_t MhShift = (Mh << 1) | carryMh;

                carryPh = nextCarryPh;
                carryMh = nextCarryMh;

                Pv[b] = MhShift | ~(Xv | PhShift);
                Mv[b] = PhShift & Xv;

                if (b == lastBlock) {
                    Pv[b] |= ~lastMask;
                    Mv[b] &= lastMask;
                }
            }
        }
        return score;
    }
};

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

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

    string secret = inf.readToken();
    if (!isValidSpell(secret)) {
        query_limit = 0;
        log_metrics();
        finish(_fail, "Invalid hidden input");
    }

    query_limit = (long long)secret.size() + 2;
    log_metrics(); 

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

    MyersED ed(secret);

    while (true) {
        string t;
        if (!(cin >> t)) {
            finish(_wa, "Contestant terminated without finding the secret");
        }

        if (!isValidSpell(t)) {
            cout << -1 << endl; 
            finish(_wa, "Invalid query");
        }

        queries++;
        if (queries > hard_cap) {
            finish(_pe, "Hard cap exceeded");
        }

        int dist = ed.distanceTo(t);
        cout << dist << endl;

        if (dist == 0) {
            finish(_ok, "Solved");
        }
    }
}


Adaptive interactor (C++):

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

static string thueMorse(int n) {
    string s;
    s.reserve(n);
    for (int i = 0; i < n; i++) {
        int x = i;
        int parity = 0;
        while (x) {
            parity ^= (x & 1);
            x >>= 1;
        }
        s.push_back(parity ? 'b' : 'a');
    }
    return s;
}

static void ensureBothLetters(string& s) {
    bool hasA = false, hasB = false;
    for (char c : s) {
        if (c == 'a') hasA = true;
        if (c == 'b') hasB = true;
    }
    if (!hasA && !s.empty()) s[rnd.next(0, (int)s.size() - 1)] = 'a';
    if (!hasB && !s.empty()) s[rnd.next(0, (int)s.size() - 1)] = 'b';
}

static string genAdversarial(int n, int style) {
    string s;
    s.reserve(n);

    auto randChar = [&]() -> char { return rnd.next(0, 1) ? 'b' : 'a'; };

    if (style == 0) {
        s = thueMorse(n);
        ensureBothLetters(s);
        return s;
    }

    if (style == 1) {
        char cur = randChar();
        int pos = 0;
        while (pos < n) {
            int remaining = n - pos;
            int maxRun = min(remaining, 60);
            int run = rnd.next(1, maxRun);
            for (int i = 0; i < run; i++) s.push_back(cur);
            pos += run;
            cur = (cur == 'a' ? 'b' : 'a');
        }
        ensureBothLetters(s);
        return s;
    }

    if (style == 2) {
        int pos = 0;
        while (pos < n) {
            int remaining = n - pos;
            int kind = rnd.next(0, 2);
            int segMax = min(remaining, 80);
            int len = rnd.next(1, segMax);

            if (kind == 0) {
                char c = randChar();
                for (int i = 0; i < len; i++) s.push_back(c);
            } else if (kind == 1) {
                char start = randChar();
                for (int i = 0; i < len; i++) {
                    s.push_back((i % 2 == 0) ? start : (start == 'a' ? 'b' : 'a'));
                }
            } else {
                for (int i = 0; i < len; i++) s.push_back(randChar());
            }
            pos += len;
        }
        ensureBothLetters(s);
        return s;
    }

    if (style == 3) {
        string half;
        half.reserve((n + 1) / 2);
        for (int i = 0; i < (n + 1) / 2; i++) half.push_back(randChar());
        s = half;
        for (int i = n / 2 - 1; i >= 0; i--) s.push_back(half[i]);

        int flips = max(1, n / 30);
        for (int k = 0; k < flips; k++) {
            int idx = rnd.next(0, n - 1);
            s[idx] = (s[idx] == 'a' ? 'b' : 'a');
        }
        ensureBothLetters(s);
        return s;
    }

    for (int i = 0; i < n; i++) s.push_back(randChar());
    for (int i = 0; i < n; i += 7) {
        if (rnd.next(0, 3) == 0) {
            char c = s[i];
            int r = min(n, i + rnd.next(1, 7));
            for (int j = i; j < r; j++) s[j] = c;
        }
    }
    ensureBothLetters(s);
    return s;
}

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

    string mode = opt<string>("mode", "non");
    ensuref(mode == "non" || mode == "adp", "Unknown mode: %s", mode.c_str());

    int nOpt = opt<int>("n", -1);
    int nmin = opt<int>("nmin", 300);
    int nmax = opt<int>("nmax", 300);
    if (nmin > nmax) swap(nmin, nmax);

    int n;
    if (nOpt != -1) n = nOpt;
    else n = rnd.next(nmin, nmax);

    n = max(1, min(300, n));

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

    int seed = 1;
    if (argc >= 2) {
        seed = atoi(argv[1]);
        if (seed <= 0) seed = 1;
    }

    string s;
    if (nOpt == -1 && seed == 1) {
        s = "a";
    } else if (nOpt == -1 && seed == 2) {
        s = string(300, 'a');
    } else if (nOpt == -1 && seed == 3) {
        s.reserve(300);
        for (int i = 0; i < 300; i++) s.push_back((i % 2 == 0) ? 'a' : 'b');
    } else {
        int style = opt<int>("style", -1);
        if (style < 0) style = rnd.next(0, 4);
        style = max(0, min(4, style));
        s = genAdversarial(n, style);
    }

    ensuref(!s.empty(), "Generated empty string");
    ensuref((int)s.size() >= 1 && (int)s.size() <= 300, "Generated invalid length: %d", (int)s.size());
    for (char c : s) ensuref(c == 'a' || c == 'b', "Invalid character generated");

    cout << s << "\n";
    return 0;
}