cf1624 F. Interacdive Problem
题意:
交互题。
给定 \(n\),有一个未知整数 \(x\),可以询问 + d,把 \(x\) 加上 \(d\) 并返回操作后 \(\lfloor \frac xn\rfloor\) 的值(注意 \(x\) 的值会被改变)
在不超过 \(10\) 次询问后猜出最后 \(x\) 的值
\(2<n\le 1000,1\le d<n\),初始 \(1\le x<n\)
思路:
\(2^{10}\approx1000\) 所以显然是二分。(然后就不会了
记最开始的数是 \(x_0\),我们二分求 \(x_0\)
设某次询问之前已经加了 \(s\),二分猜一个 \(x_0=mid\),现在准备询问 \(d=n-(mid+s)\mod n\)
那么如果真实的 \(x_0\ge mid\),回答就是 \(\lfloor \frac {mid+s+d}n\rfloor\);否则是 \(\lfloor \frac {mid+s+d}n\rfloor-1\)
最后答案是 \(x_0+s\)
还有一个问题:会不会越界?(\(1\le d<n\))
观察 \(s\) 的变化:
开始 \(s=0\),\(n>2\) 故 \(d=-mid_1\pmod n=n-\lceil n/2\rceil\) 不会越界,\(s=s+d=-mid_1 \pmod n\);
然后 \(d=mid_1-mid_2\pmod n\),其中 \(mid_1\) 表示上一次二分的中点,\(s=-mid_2 \pmod n\);
然后 \(d=mid_2-mid_3\pmod n\);以此类推。
所以每一步都不会越界。
void sol() {
int n; cin >> n;
int l = 1, r = n - 1, s = 0;
while(l < r) {
//这个mid的算法是为了跟后面的if-else配套
int mid = (l + r + 1) >> 1, d = ((-s-mid)%n+n)%n;
assert(d>0);
cout << "+ " << d << endl;
int ans; cin >> ans;
if(ans == (mid+s+d)/n) l = mid; else r = mid - 1;
s += d;
}
cout << "! " << l + s << endl;

浙公网安备 33010602011771号