CF1103B Game with modulo

一、题目

点此看题

题目描述

猜一个数 a a a,每次可以提一个问题 ( x , y ) (x,y) (x,y),如果 x ≥ y m o d    a x\geq y\mod a xymoda 返回x,否则返回y,你最多询问 60 60 60次,然后必须回答出 a a a是多少。

二、解法

一道神奇的交互题 q w q qwq qwq

首先必须明确一个结论:若 x ≥ a x\geq a xa,则 x m o d    a ≤ x / 2 x\mod a\leq x/2 xmodax/2(证明就不给了,很好意会的)

考虑倍增, l , r l,r l,r都是 2 2 2的幂次,找到最小的 l , r l,r l,r使得 l m o d    a ≥ r m o d    a l\mod a\geq r\mod a lmodarmoda,这时候一定是返回x的,结合上面的结论,就会发现这时候 l < a ≤ r l< a\leq r l<ar

得到这个区间之后,我们可以二分,判断 ( m i d , l ) (mid,l) (mid,l)会返回什么,由于一直有 l < a ≤ r l<a\leq r l<ar,所以如果返回x,那么就说明 m i d mid mid没被取模,所以 a a a一定大于 m i d mid mid,否则 m i d mid mid一定取过模, a a a一定小于等于 m i d mid mid。由于 l l l是开区间(即 a a a不会取到 l l l),分到 l + 1 = r l+1=r l+1=r是停止, l + 1 l+1 l+1就是最终的答案。

#include <cstdio>
#include <iostream>
using namespace std;
int read()
{
 int x=0,flag=1;char c;
 while((c=getchar())<'0' || c>'9') if(c=='-') flag=-1;
 while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
 return x*flag;
}
string s;
void work(int &l,int &r)
{
    do
    {
        printf("? %d %d\n",l,r);
        cin>>s;
        if(s[0]=='y') l=r,r<<=1;
    }while(s[0]=='y');
}
int main()
{
    cin>>s;
    while(s.size()!=3)
    {
        int l=0,r=1;
        work(l,r);
        while(l+1<r)
        {
            int mid=(l+r)>>1;
            printf("? %d %d\n",mid,l);
            cin>>s;
            if(s[0]=='x') l=mid;
            else r=mid;
        }
        printf("! %d\n",l+1);
        cin>>s;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值