P6682/CF1386A

挺简单的交互题。不知道为什么这题在 cf 上的版本 评了 *2700。并且有双倍经验。

首先显然是要二分答案然后用交互 check 的。我们先尝试从 P=1P=1 开始是否可行。容易发现,如果得到 ans>midans>midPP 此时原本在 n2\dfrac{n}{2} 左右,而第二次我们要找到一个 PP' 使得 PP3n4|P'-P|\approx \dfrac{3n}{4}。这显然是无解的。

不过这也启示我们应该从每次跳的距离都最大的情况去考虑,如何找到一个合法的起点。

因为极端情况下 midmid 不断变大,于是倒序考虑,先确定终点在 11,处理出每次的 midmid,在数轴上考虑,每次先往右再往左跳。跳完所有的 midmid 时在的位置就是我们要的起点。

此时就会有一个问题:会不会向左/右的空间不够导致奇怪的 PP 的重复呢?其实是不会的,因为容易发现每次就相当于把一个区间不断缩小,直到区间长度 =n2=\dfrac{n}{2}

于是我们就可以想出这么一种构造:从这个起点开始,二分同时依次向左向右跳(根据上面处理起点时的相反顺序来)。

然后又有一个问题了:这样会不会重复?感性理解一下是不会的,有具体证明可以敲敲我。

code:

ll n,m,a[107];
il ll ask(ll x,int op){
	if(op){
		printf("= %lld\n",x);
		fflush(stdout);
		return 0;
	}
	printf("? %lld\n",x);
	fflush(stdout);
	ll y;scanf("%lld",&y);
	return y;
}
void Yorushika(){
	scanf("%lld",&n),m=0;
	ll l=1,r=n-1;
	while(l<=r){
		ll mid=(l+r)>>1;
		a[++m]=mid,l=mid+1;
	}
	reverse(a+1,a+m+1);
	ll p=1;
	rep(i,1,m){
		if(i&1){
			p+=a[i];
		}else{
			p-=a[i];
		}
	}
	ll x=ask(p,0);
	l=1,r=n-1;
	ll ans=n,cnt=0;
	while(l<=r){
		ll mid=(l+r)>>1;
		cnt++;
		if(abs(m-cnt)&1){
			x=ask(p+=mid,0);
		}else{
			x=ask(p-=mid,0);
		}
		if(x){
			ans=mid;
			r=mid-1;
		}else{
			l=mid+1;
		}
	}
	ask(ans,1);
}
signed main(){
	int t=1;
		scanf("%d",&t);
	while(t--)
		Yorushika();
}