思路:20 个一组,看和第一个相同的数量得到第一个,然后推后面 19 个。
特殊情况是 10 个假的都在一个组里面。如果是最后一个组就看前 19 个,然后根据数量判第 20 个。否则就找个真的看第一个就行了。
挂了一个点。
#include<bits/stdc++.h>
using namespace std;
bool flg[1005];
int cnt;
int main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
string s;
getline(cin,s);
int p=1;
for(int i=1;i<=1000;i+=20){
if(i==981&&!cnt){
for(int j=981;j<=999;++j){
cout<<'?'<<' '<<1<<' '<<j<<endl;
cin>>flg[j];
flg[j]^=1;
if(!flg[j]) ++cnt;
}
if(cnt<10) flg[1000]=0;
else flg[1000]=1;
break;
}
int cnt0=0,cnt1=0;
for(int j=i+1;j<=i+19;++j){
cout<<'?'<<' '<<i<<' '<<j<<endl;
cin>>flg[j];
if(flg[j]) ++cnt1;
else ++cnt0;
}
if(cnt1==10||cnt0==10){
for(int j=1;j<i;++j) flg[j]=1;
for(int j=i+20;j<=1000;++j) flg[j]=1;
cout<<'?'<<' '<<(i==1?21:1)<<' '<<i<<endl;
cin>>flg[i];
flg[i]^=1;
for(int j=i+1;j<=i+19;++j) flg[j]^=flg[i];
break;
}
if(cnt1>cnt0) flg[i]=0;
else for(int j=i;j<=i+19;++j) flg[j]^=1;
for(int j=i;j<=i+19;++j) if(!flg[j]) ++cnt;
}
cout<<'!';
for(int i=1;i<=1000;++i) if(!flg[i]) cout<<' '<<i;
cout<<endl;
return 0;
}