codeforces1011D Rocket(交互题)

题目链接:

 CF-1011D

题目大意:

 常见交互题套路,有一个数字要猜,假设为 xx ;给计算机的数假设为 yy,会得到以下三种回答:

  • 若 x<yx<y,回答 −1−1;
  • 若 x==yx==y,回答 00;
  • 若 x>yx>y,回答 11;

 但是,现在计算机坏了,对于某些询问会“说谎”;所谓“说谎”就是该回答 −1−1 的回答了 11 ;反之,该回答 11 的回答了 −1−1。 
 抽象为 0101 字符串,01010101 表示第 11 、33 次询问计算机会“说谎”;若询问的次数大于了 44,就会循环;即第 55、77 次会“说谎”。 
 现在,给这个 0101 串的长度 nn,以及 xx 的最大范围 mm(即 x≤mx≤m)。 
 还要求询问次数最多不超过 6060 次。

数据范围:

 1≤m≤1091≤n≤301≤m≤1091≤n≤30

解题思路:

 一开始完全没有思路,那个 0101 串都没有给,猜上加猜?怎么猜?! 
 后来仔细一想,如果那个 0101 串确定了,就是一个很简单的交互题了,直接二分就完了。 
 难点就在怎么确定那个 0101 串?

 其实,拿 11 去问个 nn 次就可以确定那个 0101 串了; 
 如果回答为 00 ,那 xx 就是 11,这个就先不考虑了; 
 除此之外,对于每个询问,都应该满足 1<x1<x ,回答都应该是 11 ;如果不是,那这次就是在“说谎”; 
 这样恢复出那个 0101 串后,这道题就解决了。

AC代码:

/**********************************************
 *Author*        :XzzF
 *Created Time*  : 2018/7/27 23:52:41
 *Ended  Time*  : 2018/7/27 23:59:18
*********************************************/

#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <string>
#include <iostream>
#include <vector>
#include <queue>
#include <set>
#include <stack>
#include <map>
using namespace std;
typedef long long LL;
const int inf = 1 << 30;
const LL INF = 1LL << 60;

int n, m;
bool lie[50];  //lie[i]为true表示第i次会说谎

int Recover(int y) {
    printf("%d\n", y);
    fflush(stdout);
    int num;
    scanf("%d", &num);
    if(num == 0 || num == -2) exit(0);
    return num;
}

bool check(int y, int cnt) {
    printf("%d\n", y);
    fflush(stdout);
    int num;
    scanf("%d", &num);
    if(num == 0 || num == -2) exit(0);
    if(num == 1) {  //y < expect
        if(lie[cnt]) return true;
        else return false;
    }
    else if(num == -1) {   //y > expect
        if(lie[cnt]) return false;
        else return true;
    }
}

int main()
{
    scanf("%d %d", &m, &n);
    memset(lie, false, sizeof(lie));
    for(int i = 0; i < n; i++) {
        int val = Recover(1);
        if(val == -1) lie[i] = true;
    }
    int l = 1, r = m;
    int cnt = 0;
    while(l <= r) {
        int mid = (l + r) >> 1;
        if(check(mid, cnt % n)) r = mid - 1;  //忘了mod,WA了几发
        else l = mid + 1;
        cnt++;
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值