Problem: icpc2025_swerc_i
Difficulty: medium
Categories: bit, math
Time limit: 4000 ms, memory limit: 256 MB

![](images/5c297e3c3e91fd1e1bdee3a9cfa736e9b7aaa731931354b2ca00f45c9a45b3d5.jpg)

You have reached the final level of the popular roguelike game “Isaac’s Keybindings”. Instead of a boss, you encounter a shopkeeper who holds a hidden array of integers $a _ { 1 } , a _ { 2 } , \ldots , a _ { n }$ , where $0 \leq a _ { i } < 2 ^ { 3 0 }$ for each $i$ in $[ 1 , n ]$ .

It is guaranteed that the array is generated randomly, i.e., $a _ { i }$ is a uniformly random integer in $[ 0 , 2 ^ { 3 0 } )$ for each $i$ in $[ 1 , n ]$ , in all the tests excluding the example.

Let $f ( u , v ) = a _ { u } \oplus a _ { u + 1 } \oplus . . . \oplus a _ { v }$ , where $\bigoplus$ is the bitwise XOR.

You can ask queries of the following form: ? u $\mathtt { v }$ , with $1 \leq u \leq v \leq n$

The answer to the query is:

• $- 1$ , if $f ( u , v ) = 0$ ;   
• $\lfloor \log _ { 2 } ( f ( u , v ) ) \rfloor$ otherwise.

Each query has a cost of $\frac { 1 } { v - u + 1 }$ robocoins. You initially have 35 robocoins and if your balance ever becomes negative you lose. Note that your robocoin balance does not need to be an integer at any moment.

Find the answer to all possible n(n+1)2 queries without losing.

# Input

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

The first line of each test case contains one integer $n$ ( $1 \leq n \leq 1 0 0$ ) — the length of the array $a _ { 1 } , a _ { 2 } , \ldots , a _ { n }$ It is guaranteed that the array is generated randomly in all the tests excluding the example.

There are exactly 50 tests in this problem (including the example). The example has $t = 1$ and $n = 3$ and all the other tests have $t = 3 0$ and $n = 1 0 0$ .

# Interaction Protocol

For each test case, first read a single integer $n$ . If the integer you read is $- 2$ , it means that the answer to the previous test case was wrong, and you should exit immediately.

To ask a query, print a line in the format $\ ?$ u v with $1 \leq u \leq v \leq n$

As a response to the query, you will receive $- 2$ if you made an invalid query (i.e., the format is invalid, or you would reach a negative amount of robocoins). In that case, you should exit immediately. Otherwise, you will receive the answer to the query.

When you determine the answers to all the $\frac { n ( n + 1 ) } { 2 }$ queries, print them in the following format.

Print $n + 1$ lines. The first line must contain a single character !. The $i$ -th of the next $n$ lines must contain $n - i + 1$ integers: the answers to queries ? i i, ? i i+1, . . . , ? i n, respectively.

After printing a query, do not forget to output the end of line and flush the output. To do this, use:

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

# Example

<table><tr><td>standard input</td><td>standard output</td></tr><tr><td>1</td><td></td></tr><tr><td></td><td>？12</td></tr><tr><td>2</td><td></td></tr><tr><td>-1</td><td>？13</td></tr><tr><td>1</td><td>？23</td></tr><tr><td></td><td>！</td></tr><tr><td></td><td>12-1</td></tr><tr><td></td><td></td></tr><tr><td></td><td>21 2</td></tr></table>

# Note

Explanation of sample 1. In the example, the hidden array is $[ a _ { 1 } , a _ { 2 } , a _ { 3 } ] = [ 2 , 4 , 6 ]$ .

• First, you ask ? 1 2. Since $f ( 1 , 2 ) = a _ { 1 } \oplus a _ { 2 } = 6$ , the answer is $\lfloor \log _ { 2 } ( 6 ) \rfloor = 2$ .   
• Then, you ask ? 1 3. Since $f ( 1 , 3 ) = a _ { 1 } \oplus a _ { 2 } \oplus a _ { 3 } = 0$ , the answer is $- 1$ .   
• Then, you ask ? 2 3. Since $f ( 2 , 3 ) = a _ { 2 } \oplus a _ { 3 } = 2$ , the answer is $\lfloor \log _ { 2 } ( 2 ) \rfloor = 1$ .

Now, even without knowing the hidden array, you claim the answer to all the possible 6 queries. For example, you claim that the answer to $? \ 1 \ 1$ is 1.

You have spent $\begin{array} { r } { \frac { 1 } { 2 } + \frac { 1 } { 3 } + \frac { 1 } { 2 } = \frac { 4 } { 3 } } \end{array}$ robocoins, which is less than the allowed 35 robocoins.

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










static long long queries = 0;
static long long query_limit = 250000; 
static double current_cost = 0.0;
static const double BUDGET = 35.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 int get_msb_index(int x) {
    if (x == 0) return -1;
    
    
    return 31 - __builtin_clz(x);
}





void solve_test_case() {
    
    int n = inf.readInt();
    vector<int> a(n);
    for (int i = 0; i < n; ++i) {
        a[i] = inf.readInt();
    }

    
    
    vector<int> pref(n + 1, 0);
    for (int i = 0; i < n; ++i) {
        pref[i+1] = pref[i] ^ a[i];
    }

    
    cout << n << endl; 

    
    current_cost = 0.0;

    
    while (true) {
        string token;
        cin >> token;
        
        if (cin.fail()) {
            finish(_wa, "Unexpected EOF waiting for query or answer token");
        }

        if (token == "!") {
            
            
            
            for (int i = 1; i <= n; ++i) {
                for (int j = i; j <= n; ++j) {
                    int ans;
                    cin >> ans;
                    if (cin.fail()) {
                        finish(_wa, "Unexpected EOF while reading answers");
                    }

                    
                    
                    int val = pref[j] ^ pref[i-1];
                    int expected = (val == 0) ? -1 : get_msb_index(val);

                    if (ans != expected) {
                        cout << "-2" << endl; 
                        finish(_wa, "Wrong answer for range [" + to_string(i) + ", " + to_string(j) + 
                                    "]. Expected " + to_string(expected) + ", got " + to_string(ans));
                    }
                }
            }
            
            return; 
        } else {
            
            int u, v;
            bool parsed = false;

            
            if (token == "?") {
                cin >> u >> v;
                parsed = true;
            } else {
                try {
                    u = stoi(token);
                    cin >> v;
                    parsed = true;
                } catch (...) {
                    parsed = false;
                }
            }

            if (!parsed || cin.fail()) {
                finish(_wa, "Invalid query format");
            }

            queries++; 

            
            if (u < 1 || u > n || v < u || v > n) {
                cout << "-2" << endl;
                finish(_wa, "Query parameters out of bounds: " + to_string(u) + " " + to_string(v));
            }

            
            double cost = 1.0 / (double)(v - u + 1);
            current_cost += cost;
            
            if (current_cost > BUDGET + 1e-9) {
                cout << "-2" << endl;
                finish(_wa, "Robocoin budget exceeded (Limit: 35)");
            }

            
            int val = pref[v] ^ pref[u-1];
            int response = (val == 0) ? -1 : get_msb_index(val);
            cout << response << endl; 
        }
    }
}

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

    
    int t = inf.readInt();
    cout << t << endl;

    
    for (int i = 0; i < t; ++i) {
        solve_test_case();
    }

    finish(_ok, "All test cases passed");
}


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);
    
    
    
    long long seed = atoll(argv[1]);
    
    string mode = opt<string>("mode", "non");

    
    
    
    
    
    int t;
    if (seed == 1) {
        t = 1;
    } else {
        t = 30;
    }

    cout << t << endl;

    for (int i = 0; i < t; i++) {
        int n;
        vector<int> a;
        
        if (seed == 1) {
            
            n = 3;
            a = {2, 4, 6};
        } else {
            
            n = 100;
            a.resize(n);
            for (int &x : a) {
                
                x = rnd.next(0, (1 << 30) - 1);
            }
        }

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

    return 0;
}