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

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

题意

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

思路

(amod(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) 所以(xmod(b)<b<a/2)
也就是(b*k+xmod(b)<a/2)
也就是(amod(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;
}
原文地址:https://www.cnblogs.com/ttttttttrx/p/10800618.html