Problem: icpc2025_asia_yokohama_regional_f
Difficulty: medium
Categories: math
Time limit: 2000 ms, memory limit: 256 MB

You, a young astronomer, are interested in the spatial arrangement of a set of stars with distinctive features. Knowing this might contribute to the understanding of early-universe cosmology. You can perform measurements using a specialized instrument for this purpose.

The instrument uses its own three-dimensional Cartesian coordinate system, in which the origin $( 0 , 0 , 0 )$ is set on Earth, and the positions of the stars are modeled as lattice points (points whose coordinates are all integers). You already know the distances to all the stars of interest from Earth, but their directions are unknown.

In a single measurement, you specify two distinct stars, and the instrument reports the distance between them. Note that the instrument does not report the absolute or relative directions of the stars.

Determine the distances between all pairs of the stars within the limited number of measurements.

# Interaction

The first line of input contains an integer $n$ , the number of stars of interest $2 \leq n \leq 1 0 0 )$ ). The stars are numbered from 1 to $n$ . The second line contains $n$ integers. The $i$ -th of them is the squared distance from the origin to star $i$ . It is guaranteed that all stars have integer coordinates, each between $- 4 0 0 0$ and 4000, inclusive. No two stars are at the same position. No star is at the origin.

After reading in these two lines, you may start measurements. To measure the distance between stars $i$ and $j$ , write a line of the form “measure i $j ^ {  }$ , where $i$ and $j$ are distinct integers between 1 and $n$ , inclusive. In response, an input line containing an integer denoting the squared distance between stars $i$ and $j$ becomes available. You can perform up to 300 measurements.

When you have determined the distances between all pairs of the stars, write a line containing only answer, followed by $n - 1$ lines of the following format.

$$
\begin{array} { l } { d _ { 1 , 2 } \ d _ { 1 , 3 } \cdot \cdot \cdot \ d _ { 1 , n } } \\ { d _ { 2 , 3 } \cdot \cdot \cdot \ d _ { 2 , n } } \\ { \vdots } \\ { d _ { n - 1 , n } } \end{array}
$$

Here, $d _ { i , j }$ $1 \leq i < j \leq n )$ is an integer denoting the squared distance between stars $i$ and $j$ . Note that you do not need to determine the stars’ coordinates. After writing these lines, the interaction stops, and your program must terminate without any extra output.

If your output does not conform to the specifications above, or if the number of measurements exceeds 300, your submission will be judged as a wrong answer.

The coordinates of the stars are fixed before the interaction starts; they do not change during the interaction.

You are provided with a command-line tool for local testing. For more details, refer to the clarifications in the contest system.

![](images/001161dfce019aa030296ebf135f8e15920cf3265b3635dd3b1faa04e10f89c7.jpg)

In Sample Interaction 1, the stars’ coordinates can be as follows:

• star 1 is at $( 1 , 0 , 0 )$ , • star 2 is at $( - 1 , - 1 , 3 )$ , and • star 3 is at $( - 2 , 0 , 0 )$ .

The distance between stars 1 and 2 is $\sqrt { 1 4 }$ . In the first measurement, the squared distance, 14, is returned.

![](images/50f45462b7f92cd3b88fe7049446a4a418a7aac75e7d55b8ba13bf5296299c6b.jpg)  
Figure F.1. Illustration of Sample Interaction 1

Write

<table><tr><td rowspan=1 colspan=1>answer</td></tr><tr><td></td></tr><tr><td rowspan=1 colspan=1>191728099 2 191824043</td></tr><tr><td></td></tr><tr><td rowspan=1 colspan=1>191760077 12</td></tr><tr><td></td></tr><tr><td rowspan=1 colspan=1>191856029</td></tr></table>

<table><tr><td colspan="2">Read Sample Interaction 3</td><td>Write</td></tr><tr><td colspan="2">5</td><td></td></tr><tr><td colspan="2"></td><td></td></tr><tr><td colspan="2">14950149</td><td></td></tr><tr><td rowspan="6"></td><td colspan="2">answer</td></tr><tr><td colspan="2">51045162</td></tr><tr><td colspan="2">13 38 181</td></tr><tr><td colspan="2"></td></tr><tr><td colspan="2" rowspan="2">29206</td></tr><tr><td colspan="2">371</td></tr><tr><td colspan="2"></td></tr></table>

In Sample Interaction 2, the stars’ coordinates can be as follows:

• star 1 is at $\left( - 3 9 9 8 , - 3 9 9 8 , - 3 9 9 7 \right)$ , • star 2 is at (3997, 3997, 3996), • star 3 is at $\left( - 3 9 9 9 , - 3 9 9 8 , - 3 9 9 8 \right)$ , and • star 4 is at (3999, 3999, 3998).

In Sample Interaction 3, the stars’ coordinates can be as follows:

• star 1 is at $( 1 , 0 , 0 )$ , • star 2 is at $( 0 , - 2 , 0 )$ , • star 3 is at $( 0 , 0 , 3 )$ , • star 4 is at $( 3 , - 4 , 5 )$ , and • star 5 is at $\left( - 6 , 7 , - 8 \right)$ .

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


static long long queries = 0;
static long long query_limit = 300;
static bool finished = false;

struct Point {
    long long x, y, z;
};
int n;
vector<Point> stars;


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


void finish(TResult verdict, const string& msg) {
    if (finished) return;
    finished = true;
    log_metrics();
    quitf(verdict, "%s", msg.c_str());
}

long long distSq(int i, int j) {
    long long dx = stars[i].x - stars[j].x;
    long long dy = stars[i].y - stars[j].y;
    long long dz = stars[i].z - stars[j].z;
    return dx * dx + dy * dy + dz * dz;
}

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

    
    
    n = inf.readInt(2, 100, "n");
    stars.resize(n + 1);
    for (int i = 1; i <= n; ++i) {
        stars[i].x = inf.readLong(-4000LL, 4000LL, "x");
        stars[i].y = inf.readLong(-4000LL, 4000LL, "y");
        stars[i].z = inf.readLong(-4000LL, 4000LL, "z");
    }

    
    
    cout << n << endl;
    for (int i = 1; i <= n; ++i) {
        long long d2 = stars[i].x * stars[i].x + stars[i].y * stars[i].y + stars[i].z * stars[i].z;
        cout << d2 << (i == n ? "" : " ");
    }
    cout << endl;

    
    while (true) {
        
        if (queries % 10 == 0) log_metrics();
        
        
        if (queries > 200000) {
            finish(_pe, "Hard query limit exceeded.");
        }

        string token;
        
        if (!(cin >> token)) {
            finish(_pe, "Unexpected EOF waiting for command.");
        }

        bool is_query = false;
        bool is_answer = false;
        int u = -1, v = -1;

        
        
        if (token == "measure" || token == "?") {
            if (!(cin >> u >> v)) finish(_pe, "Unexpected EOF reading query arguments.");
            is_query = true;
        } else if (token == "answer" || token == "!") {
            is_answer = true;
        } else {
            
            try {
                size_t idx;
                u = stoi(token, &idx);
                if (idx != token.size()) throw exception(); 
            } catch (...) {
                finish(_pe, "Invalid token: '" + token + "'. Expected 'measure', 'answer', or star index.");
            }
            if (!(cin >> v)) finish(_pe, "Unexpected EOF reading second star index.");
            is_query = true;
        }

        if (is_answer) {
            
            long long processed = 0;
            for (int i = 1; i < n; ++i) {
                for (int j = i + 1; j <= n; ++j) {
                    string valToken;
                    if (!(cin >> valToken)) {
                        finish(_pe, "Unexpected EOF reading answer values.");
                    }
                    
                    
                    if (processed == 0 && valToken == "answer") {
                         if (!(cin >> valToken)) finish(_pe, "Unexpected EOF after 'answer'.");
                    }

                    long long userDist;
                    try {
                        userDist = stoll(valToken);
                    } catch (...) {
                        finish(_pe, "Invalid number in answer: '" + valToken + "'.");
                    }

                    long long trueDist = distSq(i, j);
                    if (userDist != trueDist) {
                        finish(_wa, format("Wrong distance for pair (%d,%d). Expected %lld, got %lld.", i, j, trueDist, userDist));
                    }
                    processed++;
                }
            }
            
            
            finish(_ok, format("Correct! Queries used: %lld.", queries));
        }

        if (is_query) {
            queries++;
            
            if (u < 1 || u > n || v < 1 || v > n) {
                finish(_pe, format("Star index out of bounds: %d %d (N=%d).", u, v, n));
            }
            if (u == v) {
                finish(_pe, format("Cannot measure distance to itself: %d.", u));
            }

            cout << distSq(u, v) << endl;
        }
    }
    
    return 0;
}


Adaptive interactor (C++):

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

using namespace std;


const int MAX_C = 4000;
const int MIN_C = -4000;

struct Point {
    int x, y, z;
    long long normSq() const {
        return 1LL * x * x + 1LL * y * y + 1LL * z * z;
    }
    bool operator<(const Point& other) const {
        return tie(x, y, z) < tie(other.x, other.y, other.z);
    }
    bool operator==(const Point& other) const {
        return tie(x, y, z) == tie(other.x, other.y, other.z);
    }
};

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

    string mode = opt<string>("mode", "non");

    
    long long seedVal = 0;
    if (argc > 1) {
        try {
            seedVal = stoll(argv[1]);
        } catch (...) {
            seedVal = 0;
        }
    }

    int n;
    
    if (seedVal == 1) n = 2;
    else if (seedVal == 2) n = 100;
    else if (seedVal == 3) n = 100;
    else {
        
        if (rnd.next(3) == 0) n = rnd.next(2, 100);
        else n = rnd.next(90, 100);
    }

    
    if (mode == "adp") n = 100;

    
    
    
    
    
    int strategy = 0;

    if (mode == "adp") {
        
        strategy = rnd.next(1, 2);
    } else {
        if (seedVal == 1) strategy = 0;
        else if (seedVal == 3) strategy = 1;
        else if (seedVal == 4) strategy = 2;
        else if (seedVal == 5) strategy = 3;
        else strategy = rnd.next(0, 3);
    }

    vector<Point> result;
    set<Point> used;

    
    if (strategy == 1) {
        map<long long, vector<Point>> buckets;
        
        int range = 250; 
        int max_ops = 3000000;
        bool found = false;

        for (int k = 0; k < max_ops; k++) {
            int x = rnd.next(-range, range);
            int y = rnd.next(-range, range);
            int z = rnd.next(-range, range);
            if (x == 0 && y == 0 && z == 0) continue;
            
            Point p = {x, y, z};
            long long d = p.normSq();
            buckets[d].push_back(p);

            
            if (buckets[d].size() >= (size_t)n + 5) {
                sort(buckets[d].begin(), buckets[d].end());
                buckets[d].erase(unique(buckets[d].begin(), buckets[d].end()), buckets[d].end());
                if (buckets[d].size() >= (size_t)n) {
                    for (int i = 0; i < n; i++) result.push_back(buckets[d][i]);
                    found = true;
                    break;
                }
            }
        }
        if (!found) strategy = 0; 
    }

    
    if (result.empty()) {
        int cx = 0, cy = 0, cz = 0;
        
        if (strategy == 3) {
            cx = rnd.next(2000, 3500) * (rnd.next(0, 1) ? 1 : -1);
            cy = rnd.next(2000, 3500) * (rnd.next(0, 1) ? 1 : -1);
            cz = rnd.next(2000, 3500) * (rnd.next(0, 1) ? 1 : -1);
        }

        while (result.size() < (size_t)n) {
            int x, y, z;
            if (strategy == 2) { 
                z = 0;
                x = rnd.next(MIN_C, MAX_C);
                y = rnd.next(MIN_C, MAX_C);
            } else if (strategy == 3) { 
                int r = 100;
                x = cx + rnd.next(-r, r);
                y = cy + rnd.next(-r, r);
                z = cz + rnd.next(-r, r);
                
                x = max(MIN_C, min(MAX_C, x));
                y = max(MIN_C, min(MAX_C, y));
                z = max(MIN_C, min(MAX_C, z));
            } else { 
                x = rnd.next(MIN_C, MAX_C);
                y = rnd.next(MIN_C, MAX_C);
                z = rnd.next(MIN_C, MAX_C);
            }

            if (x == 0 && y == 0 && z == 0) continue;
            Point p = {x, y, z};
            if (used.find(p) == used.end()) {
                used.insert(p);
                result.push_back(p);
            }
        }
    }

    
    
    
    cout << n << endl;
    shuffle(result.begin(), result.end());
    for (const auto& p : result) {
        cout << p.x << " " << p.y << " " << p.z << endl;
    }

    return 0;
}