Gym - 100851J: Jump(交互+构造+(大胆瞎搞)))
题意:给定长度为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=1010; string s,fcy; int same[maxn]; int main() { int N,i,j,ans; scanf("%d",&N); while(true){ s=""; for(i=0;i<N;i++) { char c='1'; int num=rand()%2; s+=(c-num); } cout<<s<<endl; cin>>ans; same[0]=1; if(ans==N) break; if(ans==N/2) { string tmp=s; tmp[0]=1-(s[0]-'0')+'0'; for(i=1;i<N;i++) { tmp[i]=1-(s[i]-'0')+'0'; cout<<tmp<<endl; cin>>ans; if(ans==N) return 0; if(ans==0) same[i]=1; tmp[i]=s[i]; } } for(i=0;i<N;i++) if(same[i]) s[i]=1-(s[i]-'0')+'0'; cout<<s<<endl; cin>>ans; if(ans==N) break; for(i=0;i<N;i++) s[i]=1-(s[i]-'0')+'0'; cout<<s<<endl; cin>>ans; if(ans==N) break; } return 0; }
It is your time to fight!