题意:给定长度为N的01串,现在让你猜这个串,猜的次数要不超过N+500次。 每次你猜一个串,系统会返回N/2,或N,或0。当且当有N/2个位置猜对,N个位置猜对,其他。
思路:因为信息不多,没有关联性,所以前期只有瞎猜,直到猜到一个N/2,(如果是N也ok)。猜到N/2之后,我们从这个N/2串考虑,有一半的位置是对的,有一半的位置是错的,那么我们先把第一位取反,后面挨个去取反验证,假设取反第i位,输出N/2,说明第i位和第1位正确性相反,否则相同。那么验证完后,只有两种情况,第一位是对的,第一位是错的,把两种情况带入验证,其中一个是N。
(根据题意,500次以内大概率会出现一个N/2;网上说50次就会出现一个。
(输出换行符自带缓冲,不需要再fflush(stdout)。
#include<bits/stdc++.h>
using namespace std;
const int maxn=;
string s,fcy; int same[maxn];
int main()
{
int N,i,j,ans;
scanf("%d",&N);
while(true){
s="";
for(i=;i<N;i++) {
char c=''; int num=rand()%;
s+=(c-num);
}
cout<<s<<endl;
cin>>ans; same[]=;
if(ans==N) break;
if(ans==N/) {
string tmp=s;
tmp[]=-(s[]-'')+'';
for(i=;i<N;i++) {
tmp[i]=-(s[i]-'')+'';
cout<<tmp<<endl;
cin>>ans;
if(ans==N) return ;
if(ans==) same[i]=;
tmp[i]=s[i];
}
}
for(i=;i<N;i++) if(same[i]) s[i]=-(s[i]-'')+'';
cout<<s<<endl;
cin>>ans;
if(ans==N) break;
for(i=;i<N;i++) s[i]=-(s[i]-'')+'';
cout<<s<<endl;
cin>>ans;
if(ans==N) break;
}
return ;
}