其他分享
首页 > 其他分享> > cf1103 B. Game with modulo

cf1103 B. Game with modulo

作者:互联网

题意:

交互题

有个未知整数 \(a\in[1,1e9]\),每次问两个数 \(x,y\),返回 \(x\pmod a \ge y\pmod a\) 是否成立

在 60 次内猜出 \(a\)

思路:

倍增猜法,长见识了

首先我想到猜 \(x,2x\),若 $\ge $ 说明 \(a\in [1,2x]\),否则 \(a\in [1,x)\cup (2x,1e9)\)

这样每次得到的合法区间还分开的,不知道怎么处理。

既然 \([1,x)\) 这个区间没法确定,那每次都用一个 \(\le a\) 的 \(x\) 来问不就行了!

正解:

先问 \(1,2\),若返回 \(\ge\) 则说明 \(a\in [1,2]\),否则说明 \(a>2\) 并继续;

再问 \(2,4\),返回 \(\ge\) 说明 \(a\in [3,4]\),否则 \(a>4\) 并继续;

再问 \(4,8\),返回 $\ge $ 说明 \(a\in [5,8]\),否则 \(a>8\) 并继续。

以此类推,最后一定在某次询问 \(x,2x\) 后确定 \(a\in[x+1,2x]\) 。但是注意,区间 \([1,2]\) 是特殊情况,不知道怎么处理只好特判一下。

接下来怎么办?二分!

初始 \(l=x+1,r=2x\)

每次问 \(x,mid\),若 $\ge $ 则 \(a\le mid\),于是令 \(r=mid\);否则 \(a>mid\),于是令 \(l=mid+1\)

bool ask(int x, int y) { //是否>=
    cout << "? " << x << ' ' << y << endl;
    char c; cin >> c; return c == 'x';
}
void ans(int x) {
    cout << "! " << x << endl;
}
signed main() {
    string ty; while(cin >> ty, ty != "end") {
        int x = 1; char res;
        while(!ask(x, 2*x)) x *= 2;

        if(x == 1) {
            ans(ask(0,1) ? 1 : 2);
            continue;
        }

        int l = x + (x > 1), r = x * 2;
        while(l < r) {
            int mid = (ll)l + r >> 1;
            if(ask(x, mid)) r = mid; else l = mid + 1;
        }
        ans(l);
    }
}

标签:modulo,cf1103,2x,Game,mid,int,ge,ans,ask
来源: https://www.cnblogs.com/wushansinger/p/16181281.html