gym100851J. Jump

原:P6982 [NEERC2015] Jump

很神奇啊。

注意到如果能找到一个刚好有 n2 个位置相同的串,记作 a。然后枚举 i=2n,每次反转 a1ai 的值,新串记作 b。如果此时还是刚好有 n2 个位置相同,那么说明 b1bi 与目标串的正确性相反,反之相同。于是最后可以再花 2 次询问找到目标串。下面就是要解决如何找到 a 的问题了。

有一个询问 n 次的算法:考虑初始全为 0,每次反转最前面的一个 0 直到刚好有 n2 个位置相同。正确性就是你考虑分类成 1 多还是 0 多,然后看一位一位改的影响。

但是这是 2n+1 的啊,怎么办?考虑一种神奇的做法:每次直接随机一个串判断,重复 499 次。每次询问撞到这种串的概率是 (nn2)2n,重复 499 次后得到这种串的概率极高,基本可以看作总是能找到。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
inline int read(){
	int x=0,f=1;char ch=getchar();
	while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
	while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
	return x*f;
}
int a[1005],b[1005];
signed main(){
	mt19937 rnd(time(0));
	int n=read();
	for(int i=1;i<=499;i++){
		for(int j=1;j<=n;j++)a[j]=rnd()&1;
		for(int j=1;j<=n;j++)printf("%d",a[j]);
		cout<<endl;int cnt=read();
		if(cnt==n)return 0;
		if(cnt==n/2)break;
	}
	a[1]^=1,b[1]=a[1];
	for(int i=2;i<=n;i++){
		a[i]^=1;for(int j=1;j<=n;j++)printf("%d",a[j]);
		cout<<endl;int cnt=read();
		if(cnt==n)return 0;
		b[i]=a[i]^(cnt==n/2),a[i]^=1;
	}
	for(int i=1;i<=n;i++)printf("%d",b[i]);
	cout<<endl;int cnt=read();
	if(cnt==n)return 0;
	for(int i=1;i<=n;i++)printf("%d",b[i]^1);
	return 0;
}
posted @   xx019  阅读(14)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示