Problem: icpc2025_cerc_b
Difficulty: easy
Categories: bit, math
Time limit: 1000 ms, memory limit: 256 MB

This task is interactive. After printing each line, you should flush the output buffer. You can use cout << flush in $\mathrm { C } + +$ , System.out.flush() in Java, and sys.stdout.flush() in Python. You must strictly follow the instructions in the Interaction section; otherwise you may receive verdicts like wrong answer, time limit exceeded, or others.

Since all the tasks have mythical dwarves as their main characters, it may be worth finally thinking about something tangible.

There is a hidden sequence $A$ of length $N$ consisting of integers in the range $[ 0 , 2 ^ { N } - 1 ]$ . Your task is to recover it using a limited number of queries. In each query, you provide a sequence $B$ of length $N$ with elements in the range $[ 0 , 2 ^ { N } - 1 ]$ . The response is computed as follows:

• Sequence $C$ is created where the $i$ -th element of $C$ is the bitwise xor of the $i$ -th elements of $A$ and $B$ . We denote xor by $\bigoplus$ .   
• Set $S$ is constructed as the set of all values obtainable by xoring some subset of elements of $C$ . In particular, for the empty subset, the xor is 0.   
• The answer to the query is $| S |$ .

For example, if $A = ( 1 , 4 , 3 )$ and $B = ( 0 , 4 , 7 )$ , then $C = ( 1 \oplus 0 , 4 \oplus 4 , 3 \oplus 7 ) = ( 1 , 0 , 4 )$ and $S = \{ 0 , 1 , 4 , 5 \}$ so the answer is 4.

The bitwise xor of two numbers $x$ and $y$ has bit $i$ set if and only if exactly one of $x$ and $y$ has bit $i$ set.   
For example, $5 \oplus 3 = ( 1 0 1 ) _ { 2 } \oplus ( 0 1 1 ) _ { 2 } = ( 1 1 0 ) _ { 2 } = 6 $ . In C++ and Python, xor is the operator ˆ.

# Interaction Protocol

The sequence $A$ is fixed at the start and does not depend on the queries made.

First, read a line containing one integer $1 \leq N \leq 6 0$ . Then you may ask queries.

To ask a query, print a line containing ? followed by $N$ integers in the range $[ 0 , 2 ^ { N } - 1 ]$ . In response, read one integer being the answer.

When ready, print ! followed by the $N$ integers of the hidden sequence. Then your program should exit without further output.

Remember to flush after each query and after writing the answer. Put spaces between numbers and the ?, ! symbols.

# Sample interaction

The first sample test has $N = 3$ and $A = ( 1 , 3 , 4 )$ :

<table><tr><td>Input</td><td>Output</td><td>Explanation</td></tr><tr><td>3</td><td>？123</td><td>N=3 B= (1,2,3) C = (1④1,3④2,4④3)= (0,1,7)</td></tr><tr><td>4</td><td>？00。</td><td>S = {0,1,6,7}, so the answer is 4 B = (0,0,0)</td></tr><tr><td>8</td><td>！134</td><td>C = (1④0,3④0,4④0)=(1,3,4) S = {0,1,...7}, so the answer is 8 The hidden sequence is A= (1,3,4)</td></tr></table>

# Local testing

In the Files section you can find B.zip containing sample tests and a grader grader.cpp. To test your solution, compile it, then pass the test name and your executable to the compiled ./grader:

./grader [test] [executable]

For example: ./grader 0b.in ./abc

The sample grader is not guaranteed to behave identically to the official one. However, neither is adaptive.

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


static long long queries = 0;


static long long query_limit = 5000; 


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 int compute_rank(const vector<long long>& vecs) {
    vector<long long> basis;
    for (long long x : vecs) {
        for (long long b : basis) {
            x = min(x, x ^ b);
        }
        if (x > 0) {
            basis.push_back(x);
            
            
            sort(basis.rbegin(), basis.rend());
        }
    }
    return (int)basis.size();
}

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

    
    
    int n = inf.readInt(1, 60, "N");
    vector<long long> A(n);
    for (int i = 0; i < n; ++i) {
        
        
        long long max_val = (n == 60) ? ((1LL << 60) - 1) : ((1LL << n) - 1);
        A[i] = inf.readLong(0LL, max_val, format("A[%d]", i));
    }

    
    cout << n << endl;

    
    
    long long hard_cap = 200000; 

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

        string token;
        
        if (!(cin >> token)) {
            finish(_pe, "Unexpected end of stream (expected query or answer)");
        }

        bool is_answer = false;
        vector<long long> B(n);

        
        if (token == "!") {
            is_answer = true;
            for (int i = 0; i < n; ++i) {
                if (!(cin >> B[i])) finish(_pe, "Failed to read answer element");
            }
        } else if (token == "?") {
            queries++;
            if (queries % 100 == 0) log_metrics(); 
            for (int i = 0; i < n; ++i) {
                if (!(cin >> B[i])) finish(_pe, "Failed to read query element");
            }
        } else {
            
            queries++;
            if (queries % 100 == 0) log_metrics();

            try {
                size_t idx = 0;
                B[0] = stoll(token, &idx);
                if (idx != token.size()) finish(_pe, "Invalid token in query: " + token);
            } catch (...) {
                finish(_pe, "Invalid number format: " + token);
            }

            for (int i = 1; i < n; ++i) {
                if (!(cin >> B[i])) finish(_pe, "Failed to read query element");
            }
        }

        if (is_answer) {
            
            bool ok = true;
            for (int i = 0; i < n; ++i) {
                if (A[i] != B[i]) {
                    ok = false;
                    break;
                }
            }
            if (ok) finish(_ok, "Correct sequence recovered");
            else finish(_wa, "Incorrect sequence");
        } else {
            
            
            vector<long long> C(n);
            for (int i = 0; i < n; ++i) {
                C[i] = A[i] ^ B[i];
            }
            
            int r = compute_rank(C);
            cout << (1LL << r) << endl;
        }
    }

    return 0;
}


Adaptive interactor (C++):

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

using namespace std;

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

    
    string mode = opt<string>("mode", "non");
    
    
    long long seed = atoll(argv[1]);

    int n;
    vector<long long> a;

    
    if (seed == 1) {
        
        n = 1;
        a.push_back(rnd.next(0LL, 1LL));
    } else if (seed == 2) {
        
        n = 2;
        a = {1LL, 1LL};
    } else if (seed == 3) {
        
        n = 60;
        for (int i = 0; i < n; ++i) a.push_back(1LL << i);
        shuffle(a.begin(), a.end());
    } else if (seed == 4) {
        
        n = 60;
        a.assign(n, 0);
    } else if (seed == 5) {
        
        n = 60;
        long long b1 = rnd.next(0LL, (1LL << 60) - 1);
        long long b2 = rnd.next(0LL, (1LL << 60) - 1);
        for (int i = 0; i < n; ++i) a.push_back(rnd.next(0, 1) ? b1 : b2);
    } else {
        
        int t = rnd.next(1, 100);
        if (t <= 5) n = rnd.next(1, 5);         
        else if (t <= 15) n = rnd.next(6, 20);  
        else n = rnd.next(21, 60);              

        a.resize(n);
        int strat = rnd.next(1, 4);
        
        if (strat == 1) { 
            
            for (int i = 0; i < n; ++i) {
                if (n == 60) a[i] = rnd.next(0LL, (1LL << 60) - 1);
                else a[i] = rnd.next(0LL, (1LL << n) - 1);
            }
        } else if (strat == 2) { 
            
            int r = rnd.next(1, max(1, n / 2));
            vector<long long> basis(r);
            for (int i = 0; i < r; ++i) {
                if (n == 60) basis[i] = rnd.next(0LL, (1LL << 60) - 1);
                else basis[i] = rnd.next(0LL, (1LL << n) - 1);
            }
            for (int i = 0; i < n; ++i) {
                long long val = 0;
                for (auto x : basis) if (rnd.next(0, 1)) val ^= x;
                a[i] = val;
            }
        } else if (strat == 3) { 
            
            for (int i = 0; i < n; ++i) {
                if (i > 0 && rnd.next(0, 3) > 0) a[i] = a[rnd.next(0, i - 1)];
                else {
                    if (n == 60) a[i] = rnd.next(0LL, (1LL << 60) - 1);
                    else a[i] = rnd.next(0LL, (1LL << n) - 1);
                }
            }
        } else { 
            
            for (int i = 0; i < n; ++i) {
                long long val = 0;
                int bits = rnd.next(0, min(n, 5));
                for (int k = 0; k < bits; ++k) val |= (1LL << rnd.next(0, n - 1));
                a[i] = val;
            }
        }
    }

    
    if (mode == "adp") {
        
        cout << n << endl;
    } else {
        
        cout << n << endl;
        for (int i = 0; i < n; ++i) {
            cout << a[i] << (i == n - 1 ? "" : " ");
        }
        cout << endl;
    }

    return 0;
}