标签:modulo cf1103 2x Game mid int ge ans ask
题意:
交互题
有个未知整数 \(a\in[1,1e9]\),每次问两个数 \(x,y\),返回 \(x\pmod a \ge y\pmod a\) 是否成立
在 60 次内猜出 \(a\)
思路:
倍增猜法,长见识了
首先我想到猜 \(x,2x\),若 $\ge $ 说明 \(a\in [1,2x]\),否则 \(a\in [1,x)\cup (2x,1e9)\)
这样每次得到的合法区间还分开的,不知道怎么处理。
既然 \([1,x)\) 这个区间没法确定,那每次都用一个 \(\le a\) 的 \(x\) 来问不就行了!
正解:
先问 \(1,2\),若返回 \(\ge\) 则说明 \(a\in [1,2]\),否则说明 \(a>2\) 并继续;
再问 \(2,4\),返回 \(\ge\) 说明 \(a\in [3,4]\),否则 \(a>4\) 并继续;
再问 \(4,8\),返回 $\ge $ 说明 \(a\in [5,8]\),否则 \(a>8\) 并继续。
以此类推,最后一定在某次询问 \(x,2x\) 后确定 \(a\in[x+1,2x]\) 。但是注意,区间 \([1,2]\) 是特殊情况,不知道怎么处理只好特判一下。
接下来怎么办?二分!
初始 \(l=x+1,r=2x\)
每次问 \(x,mid\),若 $\ge $ 则 \(a\le mid\),于是令 \(r=mid\);否则 \(a>mid\),于是令 \(l=mid+1\)
bool ask(int x, int y) { //是否>=
cout << "? " << x << ' ' << y << endl;
char c; cin >> c; return c == 'x';
}
void ans(int x) {
cout << "! " << x << endl;
}
signed main() {
string ty; while(cin >> ty, ty != "end") {
int x = 1; char res;
while(!ask(x, 2*x)) x *= 2;
if(x == 1) {
ans(ask(0,1) ? 1 : 2);
continue;
}
int l = x + (x > 1), r = x * 2;
while(l < r) {
int mid = (ll)l + r >> 1;
if(ask(x, mid)) r = mid; else l = mid + 1;
}
ans(l);
}
}
标签:modulo,cf1103,2x,Game,mid,int,ge,ans,ask 来源: https://www.cnblogs.com/wushansinger/p/16181281.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。