qoj12310 The Good, the Bad and the Ugly

题意

懒得总结了,直接放原文。

考虑一个数轴。一个玩家初始位于位置 \(x = p\)。在每轮开始时,你可以说“+”或“-”。之后,玩家根据你所说的内容改变位置。具体来说,如果你说 \(t\) 而玩家位于位置 \(x\),那么他将移动到位置 \(x' = x + d_t\),其中 \(d_+\)\(d_-\) 是两个整数常数。

你不知道具体的值 \(p\)\(d_+\)\(d_-\),但你知道玩家是好人、坏人或丑人(发挥你的想象力):

  • 好人玩家:\(p = m\)\(d_+ = 2\)\(d_- = -1\)
  • 坏人玩家:\(p = -m\)\(d_+ = 1\)\(d_- = -2\)
  • 丑人玩家:要么 \(p = m\) 要么 \(p = -m\),并且要么 \(d_+ = 1\)\(d_- = -1\),要么 \(d_+ = -1\)\(d_- = 1\)

如你所见,玩家的起始位置取决于某个整数常数 \(m\)\(1 \leq m \leq 1000\))……不幸的是,你也不知道它。

每轮之后,玩家会告诉你他现在是否位于 \(x = 0\)

通过进行若干轮,你可以唯一确定玩家是好人、坏人还是丑人。请在不超过 \(30m\) 轮内完成。

在每个测试中,值 \(m\)\(p\)\(d_+\)\(d_-\) 根据上述规则选择。它们预先固定,在检查过程中不会改变。

思路

假如 \(m\) 的限制为最大值(即 \(1000\times 30\)),那么我们有一个很显然的策略:往一个方向走 \(1000\) 步,再往另一个方向走 \(2000\) 步。

但是 \(m\) 的限制是动态的(\(30m\)),所以我们需要考虑逐步扩大搜索范围。

以下情况未考虑丑人,但是丑人仍可以使用此策略解决。

假如我们一开始往一个方向走了 \(a\) 步,那么这 \(a\) 步有两种情况:

  1. 离原点的距离缩小了 \(a\)

  2. 离原点的距离扩大了 \(2a\),此时需要往反方向再走 \(3a\) 步才能保证距离缩小 \(a\)

因此我们每次都以最坏情况考虑,即每次走的步数都是上一次的 \(3\) 倍,直到达到原点,达到原点后的判断是简单的。

假设交互次数为 \(q\),可以证明 \(\forall m,q\le 30m\),过程略。

代码

#include <bits/stdc++.h>
using namespace std;
int x,y,len=1,nw;
void in(){
	cin>>x;
	if(x==0) return;
	cout<<"+"<<endl,cin>>x;
	cout<<"-"<<endl,cin>>y;
	if(x+y==1){
		cout<<"! ugly"<<endl;
		exit(0);
	}
	else{
		cout<<"-"<<endl;
		cin>>x;
		cout<<(x?"! good":"! bad")<<endl;
		exit(0);
	}
}
signed main(){
	while(true){
		for(int i=1;i<=len;i++)
			cout<<(nw?'+':'-')<<endl,in();
		nw=!nw,len*=3;
	}
	return 0; 
}
posted @ 2025-09-03 20:10  WuMin4  阅读(21)  评论(0)    收藏  举报