题解:P6982 [NEERC2015] Jump

posted on 2024-11-25 13:21:46 | under | source

萌新做的第一道紫交互题纪念一下。

记串 \(S\)\(k\)\(K(S)\),答案串为 \(A\)

首先考虑怎么求一个 \(k=\frac n2\) 的串。注意到将某一位取反后 \(k\) 恰好加或减 \(1\),那么可以一开始给出全 \(0\)\(S_0\) 然后进行 \(n\) 次调整变为全 \(1\)\(S_1\),显然 \(K(S_0)+K(S_1)=n\),可以幻想一条折线,起点为 \(K(S_0)\) 终点为 \(K(S_1)\) 那么 \(k=\frac n2\) 的情况一定被折线经过。

于是我们在 \(n+1\) 次步数内求出了 \(k=\frac n2\) 的串 \(P\)

现在好做了,由于将一个位取反无法得知具体信息,所以将两个位 \(i,j\) 取反,记 \(c_i=[A_i=P_i]\),那么若取反后 \(k\) 仍为 \(\frac n2\) 那么 \(c_i\ne c_j\),反之 \(c_i=c_j\)。固定 \(i\),那么原串被划分为 \(c=c_i\)\(c\ne c_i\) 的两部分,将一部分再取反则所有的 \(c\) 相等。枚举两种情况即可。

上述部分消耗了 \(n+1\) 的步数,总计 \(2n+2\) 无法接受。

需要请出随机化大蛇了!我们可以随机生成一个串来求出 \(P\),生成出来的概率为 \(\frac {n \choose {\frac n2}}{2^n}>0.025\),进行 \(499\) 次仍无法得到 \(P\) 的概率大概是 \(3\times 10^{-6}\),非常渺小。那么总次数可以接受。

代码

#include<bits/stdc++.h>
using namespace std;

const int N = 1e5 + 5;
int n, a[N];
bool c[N]; 

inline bool get(){
	for(int i = 1; i <= n; ++i) a[i] = rand() % 2, putchar(a[i] + '0');
	putchar('\n');
	fflush(stdout);
	int k; scanf("%d", &k);
	if(k == n / 2) return true;
	return false; 
}
signed main(){
	srand(time(0));
	cin >> n;
	while(!get());
	for(int i = 2; i <= n; ++i){
		for(int j = 1; j <= n; ++j) 
			if(j == 1 || j == i) putchar((a[j] ^ 1) + '0');
			else putchar(a[j] + '0');
		putchar('\n');
		fflush(stdout);
		int k; scanf("%d", &k);
		c[i] = (k == (n / 2)); 
	}
	for(int i = 1; i <= n; ++i)
		if(!c[i]) putchar((a[i] ^ 1) + '0'); 
		else putchar(a[i] + '0');
	putchar('\n');
	fflush(stdout);
	int k; scanf("%d", &k);
	if(k == n) return 0;
	for(int i = 1; i <= n; ++i)
		if(c[i]) putchar((a[i] ^ 1) + '0');
		else putchar(a[i] + '0');
	fflush(stdout);
	return 0;
}
posted @ 2026-01-15 08:19  Zwi  阅读(1)  评论(0)    收藏  举报