CF1039B

题意

一个人初始在 \(p\) 点,你要通过不超过 \(4500\) 次询问问出这个人的位置。每次询问问这个人是否在 \([l,\ r]\) 范围内,每次询问后这个人会从 \(p\) 移动到 \([max(1,\ p\ -\ x),\ min(n,\ p\ +\ x)]\) 中的一个点,移动与询问无关。

\(1\ \leq\ n\ \leq\ 10^{18},\ 0\ \leq\ k\ \leq\ 10,\ 1\ \leq\ p\ \leq\ n\)

做法1

大范围二分,小范围随机。
随机函数:
\(rand()\) 效果很差,生成数据范围小,并且周期较短。\(rand()\) 和取模一起用的时候概率也会不相同。
使用 \(mt19937\),用法如下:

mt19937 RND(chrono::steady_clock::now().time_since_epoch().count());
uniform_int_distribution<int>(a, b)(RND);

随机产生 \([a,\ b]\)\(int\)

shuffle(permutation.begin(), permutation.end(), RND);

random_shuffle() 功能。

参考

代码

#include <bits/stdc++.h>

#ifdef DEBUG
#define debug(...) fprintf(stderr, __VA_ARGS__)
#else
#define debug(...)
#endif

#ifdef __WIN32
#define LLFORMAT "I64"
#else
#define LLFORMAT "ll"
#endif

using namespace std;

long long n;
int k;

bool Q(long long l, long long r) {
	printf("%"LLFORMAT"d %"LLFORMAT"d\n", l, r);
	fflush(stdout);
	static char s[5];
	scanf("%s", s);
	return (s[0] == 'Y');
}

int main() {
	mt19937 RND(chrono::steady_clock::now().time_since_epoch().count());
	scanf("%"LLFORMAT"d%d", &n, &k);
	long long l = 1, r = n;
	for(;;) {
		if(r - l >= 50) {
			long long mid = l + r >> 1;
			if(Q(l, mid)) {
				l = max(1ll, l - k);
				r = min(n, mid + k);
			}
			else {
				l = max(1ll, mid + 1 - k);
				r = min(n, r + k);
			}
		}
		else {
			long long p = uniform_int_distribution<int>(0, (int)(r - l))(RND) + l;
			if(Q(p, p)) return 0;
			l = max(1ll, l - k);
			r = min(n, r + k);
		}
	}
}


posted @ 2018-09-06 11:01  King_George  阅读(168)  评论(0编辑  收藏  举报