Problem: cf2109_c2
Difficulty: hard
Categories: math
Time limit: 2000 ms, memory limit: 256 MB

This is the medium version of the problem. In this version, you can send at most $\mathbf{4}$ commands.

This is an interactive problem.

Welcome, Duelists! In this interactive challenge, there is an unknown integer $x$ ($1 \le x \le 10^9$). You must make it equal to a given integer in the input $n$. By harnessing the power of "Mathmech" monsters, you can send a command to do one of the following:

|  |  |  |  |  |  |
| --- | --- | --- | --- | --- | --- |
| Command | Constraint | Result | Case | Update | Jury's response |
| "add $y$" | $-10^{18} \le y \le 10^{18}$ | $\mathrm{res} = x + y$ | $\text{if } 1 \le \mathrm{res} \le 10^{18}$ | $x \leftarrow \mathrm{res}$ | "1" |
| $\mathrm{else}$ | $x \leftarrow x$ | "0" |
| "mul $y$" | $1 \le y \le 10^{18}$ | $\mathrm{res} = x \cdot y$ | $\text{if } 1 \le \mathrm{res} \le 10^{18}$ | $x \leftarrow \mathrm{res}$ | "1" |
| $\mathrm{else}$ | $x \leftarrow x$ | "0" |
| "div $y$" | $1 \le y \le 10^{18}$ | $\mathrm{res} = x/y$ | $\text{if } y$ divides $x$ | $x \leftarrow \mathrm{res}$ | "1" |
| $\mathrm{else}$ | $x \leftarrow x$ | "0" |
| "digit" | — | $\mathrm{res} = S(x)$$^{\text{∗}}$ | — | $x \leftarrow \mathrm{res}$ | "1" |

You have to make $x$ equal to $n$ using at most $\mathbf{4}$ commands.

$^{\text{∗}}$$S(n)$ is a function that returns the sum of all the individual digits of a non-negative integer $n$. For example, $S(123) = 1 + 2 + 3 = 6$

Input

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

The first and only line of each test case contains one integer $n$ ($1 \le n \le 10^9$).

Interaction

The interaction for each test case begins by reading the integer $n$.

To send a command, output a line in the following format:

* "add $y$" Add some integer $y$ ($-10^{18} \le y \le 10^{18}$) to $x$.

  The jury will output "1" if $x + y$ is within $[1, 10^{18}]$ (successful), and "0" otherwise. If successful, update $x \leftarrow x + y$.
* "mul $y$" Multiply $x$ by a positive integer $y$ ($1 \le y \le 10^{18}$).

  The jury will output "1" if $x \cdot y$ is within $[1, 10^{18}]$ (successful), and "0" otherwise. If successful, update $x \leftarrow x \cdot y$.
* "div $y$" Divide $x$ by a positive integer $y$ ($1 \le y \le 10^{18}$).

  The jury will output "1" if $y$ is a divisor of $x$ (successful), and "0" otherwise. If successful, update $x \leftarrow \frac{x}{y}$.
* "digit" Make $x$ equal to the sum of its digits.

  The jury will always output "1" and update $x \leftarrow S(x)$.

Note that commands are case sensitive.

When you have determined that $x$ is equal to $n$, output a line in the following format:

* "!" — where the jury will output a "1" if $n$ is equal to $x$, and "-1" otherwise.

Note that answering does not count toward your limit of $\mathbf{4}$ commands.

If your program makes more than $\mathbf{4}$ commands for one test case, or makes an invalid command, then the response to the command will be "-1". After receiving such a response, your program should immediately terminate to receive the verdict Wrong Answer. Otherwise, it may receive any other verdict.

After printing a command, do not forget to output the end of the line and flush the output. Otherwise, you will get Idleness limit exceeded. To do this, use:

* fflush(stdout) or cout.flush() in C++;
* System.out.flush() in Java;
* sys.stdout.flush() in Python;
* std::io::stdout().flush() in Rust;
* see the documentation for other languages.

The interactor is non-adaptive. The unknown integer $x$ does not change during the interaction.

Example

Input

```
2
100

0

1

1

1

5

1

1

1
```

Output

```
add -10

add 1

mul 10

!

digit

div 2

!
```

Note

|  |  |  |
| --- | --- | --- |
| Solution | Jury | Explanation |
|  | $\texttt{2}$ | There are 2 test cases. |
|  | $\texttt{100}$ | In the first test case, the unknown integer $x = 9$ and we have to make it equal to $n = 100$. |
| $\texttt{add -10}$ | $\texttt{0}$ | The answer to "add -10" is "0". This means that the addition command was not successful as $x + y = 9 + (-10) \le 0$, and $x$ remains $9$ after the command |
| $\texttt{add 1}$ | $\texttt{1}$ | The answer to "add 1" is "1". This means that the addition command was successful as $x + y = 9 + 1 = 10$, and $x$ changes to $10$ after the command. |
| $\texttt{mul 10}$ | $\texttt{1}$ | The answer to "mul 10" is "1". This means that the multiplication command was successful as $x \cdot y = 10 \cdot 10 = 100$, and $x$ changes to $100$ after the command. |
| $\texttt{!}$ | $\texttt{1}$ | The answer to "!" is "1". This means you have determined that $x$ equals $n$. |
|  | $\texttt{5}$ | In the second test case, the unknown integer $x = 1234$ and we have to make it equal to $n = 5$. |
| $\texttt{digit}$ | $\texttt{1}$ | The answer to "digit" is "1". This means that $x$ turned into the sum of its digits $1 + 2 + 3 + 4 = 10$, and $x$ changes to $10$ after the command. |
| $\texttt{div 2}$ | $\texttt{1}$ | The answer to "div 2" is "1". This means that the division command was successful as $y = 2$ is a divisor of $x = 10$, and $x$ changes to $\frac{x}{y} = \frac{10}{2} = 5$ after the command. |
| $\texttt{!}$ | $\texttt{1}$ | The answer to "!" is "1". This means you have determined that $x$ equals $n$. |

Note that the empty lines in the example input and output are for the sake of clarity, and do not occur in the real interaction.

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 << '\n';
        tout << "query_limit=" << query_limit << '\n';
        tout.flush();
    } catch (...) {
        
    }
}

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

static string trimWs(const string& s) {
    size_t i = 0, j = s.size();
    while (i < j && isspace((unsigned char)s[i])) i++;
    while (j > i && isspace((unsigned char)s[j - 1])) j--;
    return s.substr(i, j - i);
}

static bool readNonEmptyLine(string& line) {
    while (true) {
        if (!std::getline(cin, line)) return false;
        line = trimWs(line);
        if (!line.empty()) return true;
    }
}

static vector<string> splitWs(const string& line) {
    vector<string> toks;
    istringstream iss(line);
    string t;
    while (iss >> t) toks.push_back(t);
    return toks;
}

static bool parseSignedInt128(const string& s, __int128& out) {
    if (s.empty()) return false;
    int sign = 1;
    size_t i = 0;
    if (s[i] == '+') {
        i++;
    } else if (s[i] == '-') {
        sign = -1;
        i++;
    }
    if (i >= s.size()) return false;

    __int128 val = 0;
    for (; i < s.size(); i++) {
        char c = s[i];
        if (c < '0' || c > '9') return false;
        val = val * 10 + (c - '0');
        if (val > (__int128)9e18) {
            
            
            
            
        }
    }
    out = val * sign;
    return true;
}

static bool parseLongLongInRange(const string& s, long long lo, long long hi, long long& out) {
    __int128 v;
    if (!parseSignedInt128(s, v)) return false;
    if (v < (__int128)lo || v > (__int128)hi) return false;
    out = (long long)v;
    return true;
}

static long long digitSumLL(long long x) {
    long long s = 0;
    while (x > 0) {
        s += x % 10;
        x /= 10;
    }
    return s;
}

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

    int t = 0;
    try {
        t = inf.readInt(1, 5000, "t");
    } catch (...) {
        
        query_limit = 0;
        log_metrics();
        quitf(_fail, "Invalid hidden input: cannot read t");
    }

    vector<long long> ns(t), xs(t);
    for (int i = 0; i < t; i++) {
        long long n = inf.readLong(1, 1000000000LL, "n");
        long long x = inf.readLong(1, 1000000000LL, "x");
        ns[i] = n;
        xs[i] = x;
    }

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

    
    log_metrics();

    cout << t << '\n';
    cout.flush();

    for (int tc = 0; tc < t; tc++) {
        long long n = ns[tc];
        long long x = xs[tc];

        cout << n << '\n';
        cout.flush();

        while (true) {
            string line;
            if (!readNonEmptyLine(line)) {
                finish(_pe, "Unexpected EOF from contestant");
            }

            vector<string> toks = splitWs(line);
            if (toks.empty()) continue;

            const string& cmd = toks[0];

            if (cmd == "!") {
                if (toks.size() != 1) {
                    cout << -1 << '\n';
                    cout.flush();
                    finish(_pe, "Invalid answer format");
                }
                if (x == n) {
                    cout << 1 << '\n';
                    cout.flush();
                    break;
                } else {
                    cout << -1 << '\n';
                    cout.flush();
                    finish(_wa, "Wrong final answer");
                }
            } else if (cmd == "digit") {
                if (toks.size() != 1) {
                    cout << -1 << '\n';
                    cout.flush();
                    finish(_pe, "Invalid digit command format");
                }
                queries++;
                if (queries > hard_cap) finish(_pe, "Hard cap exceeded");
                x = digitSumLL(x);
                cout << 1 << '\n';
                cout.flush();
            } else if (cmd == "add") {
                if (toks.size() != 2) {
                    cout << -1 << '\n';
                    cout.flush();
                    finish(_pe, "Invalid add command format");
                }
                long long y;
                if (!parseLongLongInRange(toks[1], -1000000000000000000LL, 1000000000000000000LL, y)) {
                    cout << -1 << '\n';
                    cout.flush();
                    finish(_pe, "Invalid add argument");
                }
                queries++;
                if (queries > hard_cap) finish(_pe, "Hard cap exceeded");

                __int128 res = (__int128)x + (__int128)y;
                if (res >= 1 && res <= (__int128)1000000000000000000LL) {
                    x = (long long)res;
                    cout << 1 << '\n';
                } else {
                    cout << 0 << '\n';
                }
                cout.flush();
            } else if (cmd == "mul") {
                if (toks.size() != 2) {
                    cout << -1 << '\n';
                    cout.flush();
                    finish(_pe, "Invalid mul command format");
                }
                long long y;
                if (!parseLongLongInRange(toks[1], 1LL, 1000000000000000000LL, y)) {
                    cout << -1 << '\n';
                    cout.flush();
                    finish(_pe, "Invalid mul argument");
                }
                queries++;
                if (queries > hard_cap) finish(_pe, "Hard cap exceeded");

                __int128 res = (__int128)x * (__int128)y;
                if (res >= 1 && res <= (__int128)1000000000000000000LL) {
                    x = (long long)res;
                    cout << 1 << '\n';
                } else {
                    cout << 0 << '\n';
                }
                cout.flush();
            } else if (cmd == "div") {
                if (toks.size() != 2) {
                    cout << -1 << '\n';
                    cout.flush();
                    finish(_pe, "Invalid div command format");
                }
                long long y;
                if (!parseLongLongInRange(toks[1], 1LL, 1000000000000000000LL, y)) {
                    cout << -1 << '\n';
                    cout.flush();
                    finish(_pe, "Invalid div argument");
                }
                queries++;
                if (queries > hard_cap) finish(_pe, "Hard cap exceeded");

                if (y != 0 && x % y == 0) {
                    x /= y;
                    cout << 1 << '\n';
                } else {
                    cout << 0 << '\n';
                }
                cout.flush();
            } else {
                cout << -1 << '\n';
                cout.flush();
                finish(_pe, "Unknown command");
            }
        }
    }

    finish(_ok, "OK");
    return 0;
}


Adaptive interactor (C++):

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

static long long clampLL(long long v, long long lo, long long hi) {
    if (v < lo) return lo;
    if (v > hi) return hi;
    return v;
}

static long long pickFrom(const vector<long long>& a) {
    int i = rnd.next(0, (int)a.size() - 1);
    return a[i];
}

static long long genN(long long nmax, const vector<long long>& specialN) {
    int roll = rnd.next(0, 99);
    if (roll < 40) return pickFrom(specialN);
    if (roll < 55) {
        
        int type = rnd.next(0, 4);
        if (type == 0) {
            int d = rnd.next(1, 9);
            int len = rnd.next(1, 10);
            long long v = 0;
            for (int i = 0; i < len; i++) v = v * 10 + d;
            return clampLL(v, 1LL, nmax);
        } else if (type == 1) {
            int k = rnd.next(0, 9);
            long long p10 = 1;
            for (int i = 0; i < k; i++) p10 *= 10;
            long long delta = rnd.next(-1000LL, 1000LL);
            long long v = p10 + delta;
            return clampLL(v, 1LL, nmax);
        } else if (type == 2) {
            
            long long delta = rnd.next(0LL, min(100000LL, nmax - 1));
            return nmax - delta;
        } else if (type == 3) {
            
            long long v = rnd.next(1LL, 1000LL);
            return clampLL(v, 1LL, nmax);
        } else {
            
            long long hi = min(nmax, 1000000LL);
            return rnd.next(1LL, hi);
        }
    }
    return rnd.next(1LL, nmax);
}

static long long genX(long long xmax, const vector<long long>& specialX) {
    int roll = rnd.next(0, 99);
    if (roll < 45) return pickFrom(specialX);
    if (roll < 70) {
        
        int type = rnd.next(0, 3);
        if (type == 0) return 1000000000LL;           
        if (type == 1) return 999999999LL;            
        if (type == 2) return 888888888LL;            
        return 111111111LL;                           
    }
    if (roll < 85) {
        
        if (rnd.next(0, 1) == 0) return rnd.next(1LL, 1000LL);
        long long delta = rnd.next(0LL, min(100000LL, xmax - 1));
        return xmax - delta;
    }
    return rnd.next(1LL, xmax);
}

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

    string mode = opt<string>("mode", "non");
    int tOpt = opt<int>("t", 5000);

    const long long NMAX = opt<long long>("nmax", 1000000000LL);
    const long long XMAX = opt<long long>("xmax", 1000000000LL);

    ensuref(NMAX >= 1 && NMAX <= 1000000000LL, "nmax must be in [1, 1e9]");
    ensuref(XMAX >= 1 && XMAX <= 1000000000LL, "xmax must be in [1, 1e9]");
    ensuref(tOpt >= 1 && tOpt <= 5000, "t must be in [1, 5000]");

    vector<long long> specialN = {
        1, 2, 3, 4, 5, 6, 7, 8, 9,
        10, 11, 12, 18, 19, 20,
        81, 82, 83, 89, 90, 99,
        100, 101, 109, 110, 111,
        1000, 9999, 100000, 1000000,
        123456789, 987654321, 555555555, 999999999,
        999999937, 1000000000
    };
    for (auto& v : specialN) v = clampLL(v, 1LL, NMAX);

    vector<long long> specialX = {
        1, 2, 3, 7, 8, 9,
        10, 11, 12, 18, 19, 20,
        21, 22, 27, 28,
        97, 99, 100, 101,
        999, 1000, 1001,
        1234, 9999, 10000,
        111111111, 222222222, 333333333, 444444444,
        555555555, 666666666, 777777777, 888888888, 999999999,
        123456789, 987654321,
        999999937, 1000000000
    };
    for (auto& v : specialX) v = clampLL(v, 1LL, XMAX);

    struct Case { long long n, x; };
    vector<Case> cases;

    long long seed = atoll(argv[1]);

    auto addCase = [&](long long n, long long x) {
        n = clampLL(n, 1LL, NMAX);
        x = clampLL(x, 1LL, XMAX);
        cases.push_back({n, x});
    };

    if (seed == 1) {
        
        addCase(1, 1);
        addCase(1000000000LL, 1);
        addCase(1, 1000000000LL);
        addCase(1000000000LL, 1000000000LL);
        addCase(81, 999999999LL);
        addCase(82, 1000000000LL);
        addCase(9, 999999999LL);
        addCase(10, 999999999LL);
        addCase(100, 9);
        addCase(5, 1234);
        addCase(999999937LL, 999999999LL);
        addCase(999999999LL, 1000000000LL);
        addCase(987654321LL, 123456789LL);
        addCase(123456789LL, 987654321LL);
        addCase(555555555LL, 111111111LL);
        addCase(99, 100);
        addCase(11, 10);
        addCase(19, 20);
        addCase(20, 19);
    } else if (seed == 2) {
        
        addCase(999999999LL, 999999999LL);
        addCase(1000000000LL, 999999999LL);
        addCase(999999937LL, 1000000000LL);
        addCase(1, 999999999LL);
        addCase(9, 1000000000LL);
        addCase(81, 1000000000LL);
        addCase(82, 999999999LL);
        addCase(90, 888888888LL);
        addCase(99, 111111111LL);
        addCase(100, 999999937LL);
        addCase(101, 987654321LL);
        addCase(109, 123456789LL);
        addCase(110, 555555555LL);
        addCase(111, 444444444LL);
        addCase(987654321LL, 888888888LL);
        addCase(123456789LL, 111111111LL);
        addCase(555555555LL, 999999999LL);
        addCase(10, 1);
        addCase(11, 2);
        addCase(12, 3);
    } else if (seed == 3) {
        
        int t = 5000;
        cases.reserve(t);

        
        for (int i = 0; i < 120; i++) {
            long long n = specialN[i % (int)specialN.size()];
            long long x = specialX[(i * 7) % (int)specialX.size()];
            addCase(n, x);
        }
        
        while ((int)cases.size() < t) {
            int i = (int)cases.size();
            long long n, x;
            int roll = rnd.next(0, 99);
            if (roll < 25) {
                
                x = (i % 2 == 0) ? 999999999LL : 1000000000LL;
                n = (i % 3 == 0) ? 81 : ((i % 3 == 1) ? 9 : 1000000000LL);
            } else if (roll < 50) {
                
                n = clampLL(NMAX - rnd.next(0LL, 100000LL), 1LL, NMAX);
                x = genX(XMAX, specialX);
            } else if (roll < 75) {
                
                n = genN(NMAX, specialN);
                x = pickFrom(specialX);
            } else {
                
                n = genN(NMAX, specialN);
                x = genX(XMAX, specialX);
            }
            addCase(n, x);
        }
    } else {
        int t = tOpt;
        cases.reserve(t);

        
        vector<pair<long long,long long>> curated = {
            {1, 1},
            {NMAX, 1},
            {1, XMAX},
            {NMAX, XMAX},
            {81, 999999999LL},
            {82, 1000000000LL},
            {9, 999999999LL},
            {10, 999999999LL},
            {100, 9},
            {999999937LL, 999999999LL},
            {999999999LL, 1000000000LL},
            {123456789LL, 987654321LL},
            {987654321LL, 123456789LL},
            {555555555LL, 111111111LL},
            {99, 100},
            {11, 10},
        };
        for (auto [n, x] : curated) {
            if ((int)cases.size() >= t) break;
            addCase(n, x);
        }

        
        while ((int)cases.size() < t) {
            long long n = genN(NMAX, specialN);
            long long x = genX(XMAX, specialX);

            
            
            
            int roll = rnd.next(0, 99);
            if (roll < 20) {
                x = (rnd.next(0, 1) == 0) ? 1000000000LL : 999999999LL;
                
                long long base = clampLL(NMAX - rnd.next(0LL, 1000000LL), 1LL, NMAX);
                long long tweak = rnd.next(-12345LL, 12345LL);
                n = clampLL(base + tweak, 1LL, NMAX);
            } else if (roll < 35) {
                
                long long v = 1;
                int steps = rnd.next(3, 8);
                for (int i = 0; i < steps; i++) {
                    long long p = pickFrom(vector<long long>{2, 3, 5, 7, 11, 13});
                    if (v > NMAX / p) break;
                    v *= p;
                }
                n = clampLL(v + rnd.next(-50LL, 50LL), 1LL, NMAX);
            } else if (roll < 50) {
                
                x = pickFrom(specialX);
            }

            addCase(n, x);
        }
    }

    ensuref(!cases.empty(), "No cases generated");

    if (mode == "non") {
        cout << cases.size() << "\n";
        for (auto &tc : cases) {
            cout << tc.n << " " << tc.x << "\n";
        }
    } else if (mode == "adp") {
        
        cout << cases.size() << "\n";
        for (auto &tc : cases) {
            cout << tc.n << "\n";
        }
    } else {
        ensuref(false, "Unknown mode: %s", mode.c_str());
    }

    return 0;
}