Problem: cf1578_i
Difficulty: medium
Categories: search, math
Time limit: 2000 ms, memory limit: 1024 MB

This is an interactive problem.

Your goal is to find a circle on a plane by shooting rays and getting the distance to the circle as a result.

Interactor has three hidden integer parameters that are determined in advance for each test, but which you don't know — $x_c$, $y_c$, and $r_c$. $(x_c, y_c)$ are coordinates of the circle's center and $r_c$ is its radius. The absolute values of $x_c$, $y_c$, and $r_c$ do not exceed $10^5$, and $1 \leq r_c \leq \sqrt{x_c^2 + y_c^2} - 1$.

You can shoot rays that extend from the origin $(0,0)$ and go via a point $(x_q,y_q)$ with the integer coordinates you specify. For each ray, you get a distance from the ray to the circle or $0$ if the ray intersects the circle.

Interaction

The interaction starts with your program printing a query to the standard output and finishes when your program finds and prints the answer to the problem.

Each query has a form of "? $x_q$ $y_q$", where $x_q$ and $y_q$ are integers ($|x_q|, |y_q| \le 10^6$; $x_q \ne 0$ or $y_q \ne 0$).

The interactor outputs a line with a single floating-point number — the distance between a query ray and a circle that is precise to $10^{-10}$ by an absolute value.

Your program can make the next query, read the output, and so on. You are allowed to do at most $60$ queries. At the end of the interaction, print the answer line "! $x_c$ $y_c$ $r_c$", flush the output and exit.

Note, that the output of the interactor is actually rounded to the 10-th digit after a decimal point, so if you are stress-testing your solution locally, make sure that you also perform the corresponding rounding.

Example

Input

```
? 0 -10

? 10 -10

? 10 0

? 10 10

? 10 20

? 10 30

! 20 10 10
```

Output

```
12.360679775

11.2132034356

0.0

0.0

3.416407865

5.8113883008
```

Note

 ![](https://espresso.codeforces.com/bb7538f7c31ff1ccb9aacb234a8a37ef7f96ccf3.png) Illustration of the queries from the example 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 << endl;
        tout << "query_limit=" << query_limit << endl;
    } catch (...) {
        
    }
}

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

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

    
    int xc = inf.readInt();
    int yc = inf.readInt();
    int rc = inf.readInt();

    
    query_limit = 60;

    
    log_metrics();

    
    while (true) {
        
        string query;
        int xq, yq;
        std::cin >> query;

        if (query == "?") {
            std::cin >> xq >> yq;
            queries++;

            
            double distance = sqrt((double)(xq * xq + yq * yq)) - rc;
            if (distance < 0) {
                
                std::cout << "0.0\n";
            } else {
                
                std::cout << fixed << setprecision(10) << distance << endl;
            }
            std::cout.flush();
        } else if (query == "!") {
            
            int xc_guess, yc_guess, rc_guess;
            std::cin >> xc_guess >> yc_guess >> rc_guess;
            queries++;

            
            if (xc_guess == xc && yc_guess == yc && rc_guess == rc) {
                finish(_ok, "Correct Answer");
            } else {
                finish(_wa, "Wrong Answer");
            }
        } else {
            finish(_pe, "Invalid query");
        }

        
        log_metrics();

        
        if (queries > query_limit) {
            finish(_pe, "Query limit exceeded");
        }
    }

    return 0;
}


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 << endl;
        tout << "query_limit=" << query_limit << endl;
    } catch (...) {
        
    }
}

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

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

    
    int xc = inf.readInt();
    int yc = inf.readInt();
    int rc = inf.readInt();

    
    query_limit = inf.readInt();
    log_metrics();

    
    cout << "Query limit: " << query_limit << endl;
    cout.flush();

    
    while (queries < query_limit) {
        
        int xq = inf.readInt();
        int yq = inf.readInt();

        
        double dx = xq - xc;
        double dy = yq - yc;
        double distance_to_center = sqrt(dx * dx + dy * dy);
        double result = max(0.0, distance_to_center - rc);

        
        cout << fixed << setprecision(10) << result << endl;
        cout.flush();
        queries++;

        
        if (queries >= query_limit) {
            break;
        }
    }

    
    cout << "! " << xc << " " << yc << " " << rc << endl;
    cout.flush();

    
    finish(_ok, "Completed interaction");
}


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 seedVal = 0;
    if (argc > 1) {
        seedVal = atoll(argv[1]);
    }

    const int MAX_COORD = 100000;
    int xc, yc, rc;

    
    
    
    auto isValid = [&](int x, int y, int r) {
        if (abs(x) > MAX_COORD || abs(y) > MAX_COORD) return false;
        if (r < 1) return false;
        long long d2 = 1LL * x * x + 1LL * y * y;
        long long r_limit2 = 1LL * (r + 1) * (r + 1);
        return d2 >= r_limit2;
    };

    
    auto getMaxR = [&](int x, int y) {
        long long d2 = 1LL * x * x + 1LL * y * y;
        double d = sqrt((double)d2);
        return (int)(d - 1.0);
    };

    if (seedVal == 1) {
        
        
        while (true) {
            xc = rnd.next(MAX_COORD - 5000, MAX_COORD);
            if (rnd.next(2)) xc = -xc;
            yc = rnd.next(MAX_COORD - 5000, MAX_COORD);
            if (rnd.next(2)) yc = -yc;
            rc = 1;
            if (isValid(xc, yc, rc)) break;
        }
    } else if (seedVal == 2) {
        
        
        while (true) {
            xc = rnd.next(MAX_COORD - 5000, MAX_COORD);
            if (rnd.next(2)) xc = -xc;
            yc = rnd.next(MAX_COORD - 5000, MAX_COORD);
            if (rnd.next(2)) yc = -yc;
            rc = getMaxR(xc, yc);
            
            if (rc > 5 && rnd.next(4) == 0) rc -= rnd.next(1, 5);
            if (isValid(xc, yc, rc)) break;
        }
    } else if (seedVal == 3) {
        
        
        while (true) {
            xc = rnd.next(-4, 4);
            yc = rnd.next(-4, 4);
            rc = 1;
            if (isValid(xc, yc, rc)) break;
        }
    } else if (seedVal == 4) {
        
        if (rnd.next(2)) {
            xc = rnd.next(10, MAX_COORD);
            if (rnd.next(2)) xc = -xc;
            yc = 0;
        } else {
            xc = 0;
            yc = rnd.next(10, MAX_COORD);
            if (rnd.next(2)) yc = -yc;
        }
        int max_r = getMaxR(xc, yc);
        if (max_r < 1) max_r = 1;
        rc = rnd.next(1, max_r);
        if (!isValid(xc, yc, rc)) { 
            
            xc = 10000; yc = 0; rc = 1000;
        }
    } else {
        
        while (true) {
            xc = rnd.next(-MAX_COORD, MAX_COORD);
            yc = rnd.next(-MAX_COORD, MAX_COORD);
            
            int max_r = getMaxR(xc, yc);
            if (max_r < 1) continue;

            
            int type = rnd.next(10);
            if (type == 0) rc = 1;                   
            else if (type == 1) rc = max_r;          
            else rc = rnd.next(1, max_r);            
            
            if (isValid(xc, yc, rc)) break;
        }
    }

    if (mode == "non") {
        println(xc, yc, rc);
    } else {
        
        
        println(xc, yc, rc);
    }

    return 0;
}