Problem: cf1091_g
Difficulty: easy
Categories: math
Time limit: 6000 ms, memory limit: 256 MB

Integer factorisation is hard. The RSA Factoring Challenge offered $$100\,000$ for factoring RSA-$1024$, a $1024$-bit long product of two prime numbers. To this date, nobody was able to claim the prize. We want you to factorise a $1024$-bit number.

Since your programming language of choice might not offer facilities for handling large integers, we will provide you with a very simple calculator.

To use this calculator, you can print queries on the standard output and retrieve the results from the standard input. The operations are as follows:

* + x y where $x$ and $y$ are integers between $0$ and $n-1$. Returns $(x+y) \bmod n$.
* - x y where $x$ and $y$ are integers between $0$ and $n-1$. Returns $(x-y) \bmod n$.
* \* x y where $x$ and $y$ are integers between $0$ and $n-1$. Returns $(x \cdot y) \bmod n$.
* / x y where $x$ and $y$ are integers between $0$ and $n-1$ and $y$ is coprime with $n$. Returns $(x \cdot y^{-1}) \bmod n$ where $y^{-1}$ is multiplicative inverse of $y$ modulo $n$. If $y$ is not coprime with $n$, then $-1$ is returned instead.
* sqrt x where $x$ is integer between $0$ and $n-1$ coprime with $n$. Returns $y$ such that $y^2 \bmod n = x$. If there are multiple such integers, only one of them is returned. If there are none, $-1$ is returned instead.
* ^ x y where $x$ and $y$ are integers between $0$ and $n-1$. Returns ${x^y \bmod n}$.

Find the factorisation of $n$ that is a product of between $2$ and $10$ distinct prime numbers, all of form $4x + 3$ for some integer $x$.

Because of technical issues, we restrict number of requests to $100$.

Input

The only line contains a single integer $n$ ($21 \leq n \leq 2^{1024}$). It is guaranteed that $n$ is a product of between $2$ and $10$ distinct prime numbers, all of form $4x + 3$ for some integer $x$.

Output

You can print as many queries as you wish, adhering to the time limit (see the Interaction section for more details).

When you think you know the answer, output a single line of form ! k p\_1 p\_2 ... p\_k, where $k$ is the number of prime factors of $n$, and $p_i$ are the distinct prime factors. You may print the factors in any order.

Example

Input

```
21  
  
7  
  
17  
  
15  
  
17  
  
11  
  
-1  
  
15
```

Output

```
+ 12 16  
  
- 6 10  
  
* 8 15  
  
/ 5 4  
  
sqrt 16  
  
sqrt 5  
  
^ 6 12  
  
! 2 3 7
```

Note

We start by reading the first line containing the integer $n = 21$. Then, we ask for:

1. $(12 + 16) \bmod 21 = 28 \bmod 21 = 7$.
2. $(6 - 10) \bmod 21 = -4 \bmod 21 = 17$.
3. $(8 \cdot 15) \bmod 21 = 120 \bmod 21 = 15$.
4. $(5 \cdot 4^{-1}) \bmod 21 = (5 \cdot 16) \bmod 21 = 80 \bmod 21 = 17$.
5. Square root of $16$. The answer is $11$, as $(11 \cdot 11) \bmod 21 = 121 \bmod 21 = 16$. Note that the answer may as well be $10$.
6. Square root of $5$. There is no $x$ such that $x^2 \bmod 21 = 5$, so the output is $-1$.
7. $(6^{12}) \bmod 21 = 2176782336 \bmod 21 = 15$.

We conclude that our calculator is working, stop fooling around and realise that $21 = 3 \cdot 7$.

Non-adaptive interactor (C++):
#include "testlib.h"

#include <algorithm>
#include <iostream>
#include <numeric>
#include <string>
#include <vector>

using namespace std;

using i128 = __int128_t;

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

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

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

static long long mod_norm(long long x, long long mod) {
    x %= mod;
    if (x < 0) x += mod;
    return x;
}

static long long mod_mul(long long a, long long b, long long mod) {
    return (long long)((i128)a * (i128)b % (i128)mod);
}

static long long mod_pow(long long a, unsigned long long e, long long mod) {
    long long r = 1 % mod;
    a = mod_norm(a, mod);
    while (e) {
        if (e & 1ULL) r = mod_mul(r, a, mod);
        a = mod_mul(a, a, mod);
        e >>= 1ULL;
    }
    return r;
}

static long long ext_gcd(long long a, long long b, long long& x, long long& y) {
    if (b == 0) {
        x = 1;
        y = 0;
        return a;
    }
    long long x1 = 0, y1 = 0;
    long long g = ext_gcd(b, a % b, x1, y1);
    x = y1;
    y = x1 - (a / b) * y1;
    return g;
}

static long long mod_inv(long long a, long long mod) {
    long long x = 0, y = 0;
    long long g = ext_gcd(a, mod, x, y);
    if (g != 1 && g != -1) return 0;
    return mod_norm(x, mod);
}

static long long crt_pair(long long a1, long long m1, long long a2, long long m2) {
    
    long long inv = mod_inv(mod_norm(m1, m2), m2);
    if (inv == 0) die(_fail, "CRT failed: no inverse");
    long long t = mod_norm(a2 - a1, m2);
    t = mod_mul(t, inv, m2);
    long long res = (long long)((i128)a1 + (i128)m1 * (i128)t);
    long long mod = (long long)((i128)m1 * (i128)m2);
    return mod_norm(res, mod);
}

static long long sqrt_mod_blum(long long a, long long n, const vector<long long>& primes) {
    if (std::gcd(a, n) != 1) return -1;
    if (primes.empty()) return -1;

    vector<long long> rs;
    rs.reserve(primes.size());
    for (long long p : primes) {
        long long ai = mod_norm(a, p);
        long long e = (p + 1) / 4;
        long long r = mod_pow(ai, (unsigned long long)e, p);
        if (mod_mul(r, r, p) != ai) return -1;
        rs.push_back(r);
    }

    long long cur = rs[0];
    long long mod = primes[0];
    for (size_t i = 1; i < primes.size(); i++) {
        cur = crt_pair(cur, mod, rs[i], primes[i]);
        mod = (long long)((i128)mod * (i128)primes[i]);
    }
    return mod_norm(cur, n);
}

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

    int k = inf.readInt();
    if (k < 2 || k > 10) die(_fail, "Invalid hidden input: k out of range");

    vector<long long> primes;
    primes.reserve(k);
    for (int i = 0; i < k; i++) {
        long long p = inf.readLong();
        if (p <= 1) die(_fail, "Invalid hidden input: p <= 1");
        if (p % 4 != 3) die(_fail, "Invalid hidden input: p % 4 != 3");
        primes.push_back(p);
    }
    sort(primes.begin(), primes.end());
    if (adjacent_find(primes.begin(), primes.end()) != primes.end()) die(_fail, "Duplicated primes");

    const long long N_MAX = 9000000000000000000LL;
    long long n = 1;
    for (long long p : primes) {
        if ((i128)n * (i128)p > (i128)N_MAX) die(_fail, "Hidden n exceeds 64-bit limit");
        n = (long long)((i128)n * (i128)p);
    }
    if (n < 21) die(_fail, "Invalid hidden input: n < 21");

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

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

    while (true) {
        string cmd;
        if (!(cin >> cmd)) {
            die(_wa, "Unexpected EOF from solution");
        }

        if (cmd == "!") {
            int out_k = 0;
            if (!(cin >> out_k)) die(_wa, "Invalid answer format");
            if (out_k < 2 || out_k > 10) die(_wa, "Invalid answer k");

            vector<long long> out_ps;
            out_ps.reserve(out_k);
            for (int i = 0; i < out_k; i++) {
                long long p;
                if (!(cin >> p)) die(_wa, "Invalid answer factor");
                out_ps.push_back(p);
            }
            sort(out_ps.begin(), out_ps.end());
            out_ps.erase(unique(out_ps.begin(), out_ps.end()), out_ps.end());
            if (out_ps != primes) die(_wa, "Wrong factorization");
            die(_ok, "OK");
        }

        queries++;
        if (queries > hard_cap) die(_pe, "Too many queries (hard cap)");

        if (cmd == "+") {
            long long x, y;
            if (!(cin >> x >> y)) die(_wa, "Invalid '+' query");
            if (x < 0 || x >= n || y < 0 || y >= n) die(_wa, "Out of range '+' args");
            cout << mod_norm(x + y, n) << endl;
            cout.flush();
            continue;
        }
        if (cmd == "-") {
            long long x, y;
            if (!(cin >> x >> y)) die(_wa, "Invalid '-' query");
            if (x < 0 || x >= n || y < 0 || y >= n) die(_wa, "Out of range '-' args");
            cout << mod_norm(x - y, n) << endl;
            cout.flush();
            continue;
        }
        if (cmd == "*") {
            long long x, y;
            if (!(cin >> x >> y)) die(_wa, "Invalid '*' query");
            if (x < 0 || x >= n || y < 0 || y >= n) die(_wa, "Out of range '*' args");
            cout << mod_mul(x, y, n) << endl;
            cout.flush();
            continue;
        }
        if (cmd == "/") {
            long long x, y;
            if (!(cin >> x >> y)) die(_wa, "Invalid '/' query");
            if (x < 0 || x >= n || y < 0 || y >= n) die(_wa, "Out of range '/' args");
            if (std::gcd(y, n) != 1) {
                cout << -1 << endl;
                cout.flush();
                continue;
            }
            long long inv = mod_inv(y, n);
            if (inv == 0) {
                cout << -1 << endl;
                cout.flush();
                continue;
            }
            cout << mod_mul(x, inv, n) << endl;
            cout.flush();
            continue;
        }
        if (cmd == "sqrt") {
            long long x;
            if (!(cin >> x)) die(_wa, "Invalid 'sqrt' query");
            if (x < 0 || x >= n) die(_wa, "Out of range 'sqrt' arg");
            cout << sqrt_mod_blum(x, n, primes) << endl;
            cout.flush();
            continue;
        }
        if (cmd == "^") {
            long long x, y;
            if (!(cin >> x >> y)) die(_wa, "Invalid '^' query");
            if (x < 0 || x >= n || y < 0 || y >= n) die(_wa, "Out of range '^' args");
            cout << mod_pow(x, (unsigned long long)y, n) << endl;
            cout.flush();
            continue;
        }

        die(_pe, "Unknown command: " + cmd);
    }
}


Adaptive interactor (C++):

Test generator (C++):
#include "testlib.h"

#include <bits/stdc++.h>

using namespace std;

using u64 = unsigned long long;
using u128 = __uint128_t;

static u64 mod_mul(u64 a, u64 b, u64 mod) {
    return (u128)a * b % mod;
}

static u64 mod_pow(u64 a, u64 e, u64 mod) {
    u64 r = 1 % mod;
    while (e) {
        if (e & 1) {
            r = mod_mul(r, a, mod);
        }
        a = mod_mul(a, a, mod);
        e >>= 1;
    }
    return r;
}

static bool is_prime_u64(u64 n) {
    if (n < 2) return false;
    for (u64 p: {2ULL, 3ULL, 5ULL, 7ULL, 11ULL, 13ULL, 17ULL, 19ULL, 23ULL, 29ULL, 31ULL, 37ULL}) {
        if (n % p == 0) return n == p;
    }
    u64 d = n - 1;
    int s = 0;
    while ((d & 1) == 0) {
        d >>= 1;
        s++;
    }

    
    
    static const u64 bases[] = {2ULL, 325ULL, 9375ULL, 28178ULL, 450775ULL, 9780504ULL, 1795265022ULL};
    for (u64 a: bases) {
        if (a % n == 0) continue;
        u64 x = mod_pow(a % n, d, n);
        if (x == 1 || x == n - 1) continue;
        bool ok = false;
        for (int r = 1; r < s; r++) {
            x = mod_mul(x, x, n);
            if (x == n - 1) {
                ok = true;
                break;
            }
        }
        if (!ok) return false;
    }
    return true;
}

static u64 sample_blum_prime(int bits) {
    
    
    bits = max(10, min(bits, 62));
    const long long lo = (1LL << (bits - 1));
    const long long hi = (1LL << bits) - 1;
    for (;;) {
        long long x = rnd.next(lo, hi);
        x |= 1LL;              
        x = (x & ~3LL) | 3LL;  
        if (x > hi) x -= 4;
        if (x < lo) x += 4;
        if (x < 7) x = 7;
        const u64 p = (u64)x;
        if (is_prime_u64(p)) return p;
    }
}

int main(int argc, char** argv) {
    registerGen(argc, argv, 1);
    (void)opt<string>("mode", "non");

    long long seed_val = -1;
    try {
        seed_val = stoll(string(argv[1]));
    } catch (...) {
        seed_val = -1;
    }

    vector<u64> primes;
    if (seed_val == 1) {
        primes = {3ULL, 7ULL};
    } else if (seed_val == 2) {
        primes = {3ULL, 7ULL, 11ULL};
    } else if (seed_val == 3) {
        primes = {3ULL, 7ULL, 11ULL, 19ULL, 23ULL};
    } else {
        
        
        const u64 N_MAX = 9000000000000000000ULL;  
        __uint128_t prod = 1;
        int target = rnd.next(2, 10);
        unordered_set<u64> used;
        primes.reserve(target);
        for (int tries = 0; tries < 200000 && (int)primes.size() < target; tries++) {
            int bits = rnd.next(10, 20);  
            u64 p = sample_blum_prime(bits);
            if (!used.insert(p).second) continue;
            if (prod * (__uint128_t)p > (__uint128_t)N_MAX) continue;
            primes.push_back(p);
            prod *= (__uint128_t)p;
        }
        if ((int)primes.size() < 2) primes = {3ULL, 7ULL};
    }

    cout << primes.size() << "\n";
    for (u64 p: primes) {
        cout << p << "\n";
    }
    return 0;
}