Description
这是一道交互题
有A个诚实的人和B个不诚实的人,每次可以操作(x,y)表示向x询问y是否是诚实人。若x诚实则如实回答,否则将会以一定策略回答
问能否在2n次询问内求出每个人是否诚实
1≤A,B≤20001\le A,B\le20001≤A,B≤2000
Solution
首先若A<=B则肯定不行,因为可以从B里面挑A个伪装成A
若A>B,那么我们的策略就是先找到一个真人,然后n次问完剩余全部
考虑维护一条链,其中每个人都认为前一个是真的,那么如果出现了一个假的我们就抵消掉
因为A>B,而我们最后一定得到了一条全部认为是真的的链,并且其中只要有一个人是真的那么出度为0的点就是真的
所以就得到了一个一定真的的人,再问n-1次就可以了
Code
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
const int N=200005;
int ans[N],stack[N],top;
int main(void) {
int a,b; scanf("%d%d",&a,&b);
if (a<=b) return 0&printf("Impossible\n");
int n=a+b;
rep(i,0,n-1) {
if (!top) {
stack[++top]=i;
continue;
}
printf("? %d %d\n", stack[top],i);
fflush(stdout);
char ch[2]; scanf("%s",ch);
if (ch[0]=='Y') stack[++top]=i;
else top--;
}
ans[stack[top]]=1;
rep(i,0,n-1) if (i!=stack[top]) {
printf("? %d %d\n", stack[top],i);
fflush(stdout);
char ch[2]; scanf("%s",ch);
if (ch[0]=='Y') ans[i]=1;
}
printf("! ");
rep(i,0,n-1) putchar(ans[i]+'0');
puts("");
return 0;
}