鱼香rose'Blog

2023年ccpc重庆站女生专场B

\(\Huge{2023ccpc重庆站女生专场B.终焉之茧}\)

题目链接:B. 终焉之茧

题意

给定一个无限大的平面,终焉之茧坐标为\([x_0,y_0]\),数据保证\(-10^3\le x_0,y_0 \le 10^3\)

初始会给出终焉之茧与\([0,0]\)坐标的距离\(f(d)=(x-x_0)^2+(y-y_0)^2\)

然后我们可以查询至多30次:

  • dx dy:将当前坐标\([x,y]\)移动到\([x+dx,y+dy]\),然后会返回当前坐标距离终焉之茧的距离\(f(d)\)
  • 若距离\(f(d)=0\)时,表示找到终焉之茧,结束!
  • \(-2000 \le dx,dy \le 2000\)

思路

  • 根据\(x_0,y_0,dx,dy\)的数据范围,可知平面大小实际上为\(-1000 \le x,y \le 1000\),意味着每次可以到达平面任意一点。
  • 我们可以考虑分别二分\(x,y\),然后就可以在\(2 \times \log_{2}{2000}\)次查询内找到终焉之茧。

标程

#define int long long
int nowx, nowy;
int ask(int x, int y) {
    //因为查询时不是直接查坐标,而是移动距离,所以要减去当前坐标
    cout << x - nowx << ' ' << y - nowy << endl; fflush(stdout);
    nowx = x, nowy = y;
    int z; cin >> z;
    return z;
}
void Solved() {
    int d, mid, l = -1000, r = 1000;
    cin >> d;
    if(!d) return;

    int d1 = ask(-1000, 0);
    if(!d1) return;
    int d2 = ask(1000, 0);
    if(!d2) return;

    while(l < r) {//查找坐标x的位置
        if(d1 < d2) {
            mid = l + r >> 1;
            d2 = ask(mid, nowy);
            if(!d2) return;
            r = mid;
        } else if(d1 > d2) {
            mid = l + r + 1 >> 1;
            d1 = ask(mid, nowy);
            if(!d1) return;
            l = mid;
        } else {
            mid = l + r >> 1;
            if(ask(mid, nowy) == 0) return;
            break;
        }
    }
    l = -1000, r = 1000;
    d1 = ask(nowx, -1000);
    if(!d1) return;
    d2 = ask(nowy, 1000);
    if(!d2) return;

    while(l < r) {//查找坐标y的位置
        if(d1 < d2) {
            mid = l + r >> 1;
            d2 = ask(nowx, mid);
            if(!d2) return;
            r = mid;
        } else if(d1 > d2) {
            mid = l + r + 1 >> 1;
            d1 = ask(nowx, mid);
            if(!d1) return;
            l = mid;
        } else {
            mid = l + r >> 1;
            if(ask(nowx, mid) == 0) return;
            break;
        }
    }
}
posted @ 2026-01-15 21:51  鱼香_rose  阅读(0)  评论(0)    收藏  举报