D. Game with modulo
题意:
求一个数字
a
(
1
−
1
e
9
)
a(1-1e9)
a(1−1e9),最多询问60次。
每次询问输入
x
,
y
x,y
x,y
当
(
x
m
o
d
a
)
≥
(
y
m
o
d
a
)
(x \mod a)\ge (y \mod a)
(xmoda)≥(ymoda) 输出
x
x
x否则输出
y
y
y。
题解:
首先分析一下若
a
a
a在
(
x
,
2
x
]
(x,2x]
(x,2x]区间内,询问
?
x
? x
?x
2
x
2x
2x返回必为
x
x
x;
因此可以依次询问
(
0
,
1
)
,
(
1
,
2
)
,
(
2
,
4
)
,
…
,
(
2
29
,
2
30
)
(0,1),(1,2),(2,4),\dots,(2^{29},2^{30})
(0,1),(1,2),(2,4),…,(229,230),
a
a
a所在的区间必为第一个返回
x
x
x的区间;
区间找到之后,在
(
x
,
2
x
]
(x,2x]
(x,2x]内二分就好,(感觉自己二分不太熟练,经常出错,有待加强。)
代码:
#include<bits/stdc++.h>
using namespace std;
string s;
int base[39];
char query(int x,int y){
cout<<"?"<<" "<<x<<" "<<y<<endl;
fflush(stdout);
char c;
cin>>c;
return c;
}
int half(int l,int r){
int mid,ans,ll=l,rr=r;
if(query(0,l)=='x')return l;
/* while(ll<=rr){ //写法一,比较笨,调了好多次
mid=(ll+rr+1)>>1;
if(mid==l)break;
if(query(l,mid)=='x')ans=mid,rr=mid-1;
else ll=mid+1;
}
return ans;
*/
while(l+1<r){ //写法二,借鉴来的
mid=(l+r)>>1;
if(query(l,mid)=='y')l=mid;
else r=mid;
}
return l+1;
}
void solve(){
vector<int>ans;ans.clear();
for(int i=0;i<30;i++)if(query(base[i],base[i+1])=='x'){ans.push_back(i);break;}
for(int i=0;i<1;i++){
int as=half(base[ans[i]],base[ans[i]+1]);
cout<<"! "<<as<<endl;
}
// fflush(stdout);
}
int main(){
// freopen("tt.in","r",stdin),freopen("tt.out","w",stdout);
base[0]=1;
for(int i=1;i<=30;i++)base[i]=base[i-1]*2;
while(cin>>s){
if(s=="start")solve();
else return 0;
}
}