CF 1780-D. Bit Guessing Game_Codeforces Round #846 (Div. 2) D

Posted JustACommonMan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF 1780-D. Bit Guessing Game_Codeforces Round #846 (Div. 2) D相关的知识,希望对你有一定的参考价值。

一道交互题

有一个数字a(1<=a<=1e9),给出它的二进制表示中\'1\'的数目

最多30次询问,每次询问输出"- x",之后给出a-x后的二进制表示中\'1\'的数目,最后以这样的形式"! ans"输出原数字ans

a最大最高位的1是在从右往左的第30位(否则如果从右往左31位为1,那么a>=2^30,即a>=1024*1024*1024,但是a<=1e9)

从右往左依次输出1<<0, 1<<1, 1<<2, ...

设减之前的\'1\'的位数为cnt1,减之后\'1\'的位数为cnt2

当输出1<<j时:

  如果cnt2<cnt1,说明原数字中1<<j这个位置上确实是1,那么ans|=1<<j, cnt1=cnt2, flag=false

  如果cnt2>=cnt1,说明原数字中1<<j这个位置上是0,比如1000,输出1<<0后,数字变成0111,这个时候进入flag=true模式(cnt1不更改),之后j++,然后输出1<<(j-1),直到cnt2<cnt1

  当cnt2<cnt1时,说明多出的1全部都减没了,相当于减去了最开始的1000中的1,此时1<<j的位置就是1000中1所在的位置,所以ans|=1, cnt1=cnt2, flag=false

 #include <bits/stdc++.h>
 using namespace std;
 void solve()
 
     int cnt, ans=0;
     bool flag=false;
     scanf("%d", &cnt);
     for(int j=0; j<30; j++)
         if(cnt>0)
             if(!flag)
                 printf("- %d\\n", 1<<j), fflush(stdout);
             else
                 printf("- %d\\n", 1<<(j-1)), fflush(stdout);
             int cnt2;
             scanf("%d", &cnt2);
             if(cnt2<cnt)
                 ans|=1<<j;
                 flag=false;
                 cnt=cnt2;
             else
                 flag=true;
             
         
     
     printf("! %d\\n", ans);
     fflush(stdout);
     //比如1000,第一次减1<<0,会变成0111,cnt2>cnt所以flag=true接下来就一直1<<(j-1),直到多出来的1减没,这样减去1<<(1-1), 1<<(2-1), 1<<(3-1)后,得到的cnt2=0<cnt1=1,这表明j=3时, 1<<3是原本数字中的位,所以ans|=1<<j,然后flag从true变成false 
 
 int main(void)
 
     int T=1;
     scanf("%d", &T);
     while(T--)solve();
     return 0;
  

 

以上是关于CF 1780-D. Bit Guessing Game_Codeforces Round #846 (Div. 2) D的主要内容,如果未能解决你的问题,请参考以下文章

CF1486 C2. Guessing the Greatest (hard version)

bzoj4430 [Nwerc2015]Guessing Camels赌骆驼

BZOJ 4430 Guessing Camels赌骆驼

CF869 E 二维BIT

CF1109A Sasha and a Bit of Relax

rst003_guessing game