【AtCoder Regular Contest 078 E】Awkward Response
交互题,二分。
题目大意:
你要猜一个数 $N$,你每次可以询问 $n$,然后交互库会在以下情况时返回 Y
:
- $n\leq N$ 且 $n$ 的字典序小于等于 $N$ 的字典序。
- $n\gt N$ 且 $n$ 的字典序严格大于 $N$ 的字典序。
否则会返回 N
。
你要在 $64$ 次询问中得到答案。
题解:
首先确定有多少位。可以从 $10^9$ 开始询问,每次减少一个 $0$。碰到 Y
说明这时位数刚好。有一个例外:$N$ 是 $10$ 的幂次,那么永远都是 Y
,则还得对每个 $10^x$,判断一下 $10^x-1$。
确定最高位是多少,直接枚举每一位是什么即可。
确定之后的位是多少,只要二分这位是什么即可。
$64$ 次操作完全够用。
Code:
#include<cstdio>
int ans,w=1e9;
char o[5],lst;
int main(){
while(w!=1){
printf("? %d\n",w),fflush(stdout),scanf("%s",o);
if(*o=='Y'){
printf("? %d\n",w-1),fflush(stdout),scanf("%s",o);
if(*o=='N'||lst=='N')break;
}
lst=*o;
w/=10;
}
if(w==1e9){printf("! %d\n",w),fflush(stdout);return 0;}
if(w==1){
for(int i=1;i<10;++i){
printf("? %d0\n",i),fflush(stdout),scanf("%s",o);
if(*o=='Y'){printf("! %d\n",i),fflush(stdout);return 0;}
}
}else{
for(int i=1;i<10;++i){
printf("? %d\n",i),fflush(stdout),scanf("%s",o);
if(*o=='N')break;
ans=i*w;
}
for(w/=10;w;w/=10){
int l=0,r=9,s=0;
while(l<=r){
const int mid=l+r>>1;
printf("? %lld\n",(ans+mid*w+w)*10LL-1);
fflush(stdout),scanf("%s",o);
if(*o=='N')l=mid+1;else r=(s=mid)-1;
}
ans+=s*w;
}
}
printf("! %d\n",ans),fflush(stdout);
return 0;
}