D. Game with modulo 交互题(取余(膜)性质)附带a mod b<a/2证明

D. Game with modulo 交互题(取余(膜)性质)

题意

猜一个点\(a\)可以向机器提问 点对\((x,y)\)
如果\(x\mod(a)>=y\mod(a)\)回答\(x\)
反之回答\(y\)
询问不能超过60下,请你猜出a

思路

\(a\mod(b)<a/2(a>=b)\)
形式化的证明: a的二进制形式是1xxxxxx b的二进制形式是0001xxx
\(a=b*k+x\) 设a和b最高位二进制的位数差为\(z\)
\(k=1<<(z-1)\)
这时 b*k的二进制形式是01xxx000
\(a-b*k=x\) 其中\(b*k>=a/2\) 所以\(x<=a/2\)
再来讨论相等的情况
假设\(x=a/2\)
所以\(x>=b\) 所以\(x\mod(b)<b<a/2\)
也就是\(b*k+x\mod(b)<a/2\)
也就是\(a\mod(b)<a/2\) 故得证
所以本题中 只要枚举(0,1) (1,2)(2,3) 第一个使得返回y的范围里面 有a,然后二分再找a即可

#include<bits/stdc++.h>
#define FOR(i,f_start,f_end) for(int i=f_start;i<=f_end;i++)
#define MS(arr,arr_value) memset(arr,arr_value,sizeof(arr)) 
#define F first 
#define S second
#define pii pair<int ,int >
#define mkp make_pair
#define pb push_back
using namespace std;
typedef long long ll;
string opt;
int main(){
    while(cin>>opt){
        if(opt[0]=='s'){
            
            ll l=0,r=1;
            for(;;){
                cout<<"? "<<l<<" "<<r<<endl;
                fflush(stdout);
                cin>>opt;
                if(opt=="x")break;
                l=r;
                r<<=1;
            }
            while(l<r){
                ll mid=l+r>>1;
                cout<<"? "<<mid<<" "<<r<<endl;
                fflush(stdout);
                cin>>opt;
                if(mid+1==r){
                    cout<<"! ";
                    if(opt=="x"){
                        cout<<r<<endl;
                    }
                    else cout<<mid<<endl;
                    break;
                }
                if(opt=="x"){
                    l=mid;
                }
                else if(opt=="y")r=mid;

            }

        }
        else if(opt[0]=='e')break;
    }

    return 0;
}

猜你喜欢

转载自www.cnblogs.com/ttttttttrx/p/10800618.html
今日推荐