EOJ Monthly 2018.11 猜價格 (模擬)
阿新 • • 發佈:2018-11-19
分三種情況:
1.k=1。此時每次都說反話,反著二分即可。
2.1<k <= n。那麼在前n次問答中一定會出現一次錯誤,通過不斷輸出1找出那個錯誤發生的位置(若回答是>那這就是錯誤)。此後每隔k次就會有一個錯誤發生,判斷出來即可。
3.k > n。不能用上面的方式,否則回答次數會超過2n。因為k>n,所以在2n次問答中只會出現一個錯誤,所以通過每次輸出兩個同樣的數,判斷是否出現錯誤。當兩次得到應答不一致時,就說明錯誤發生,再輸出一個同樣的數確定是非。此外便可以正常二分。
*清空緩衝區要用cin
#include<bits/stdc++.h> using namespace std; const int mod = 1e9+7; typedef long long LL; LL n,k; void gao1() { LL mid,L= 1, R= ((1LL)<<n)-1; char c; while(L<=R){ mid = L+(R-L)/2; printf("%lld\n",mid); cin>>c; if(c== '=' ){ break; } else if(c== '<' ){ R = mid-1; } else{ L = mid+1; } } } void gao2() { int pos; char c; for(int i=1;i<=n;++i){ printf("1\n"); cin>>c; if(c=='>'){ break; } } LL mid,L= 1, R= ((1LL)<<n)-1; int cnt = 1; while(L<=R){ mid = L+(R-L)/2; printf("%lld\n",mid); cin>>c; if(c=='=') break; else if(c=='<'){ if(cnt==k){ cnt = 0; R = mid-1; } else L = mid+1; } else{ if(cnt==k){ cnt = 0; L = mid+1; } else{ R = mid-1; } } cnt++; } } void gao3() { LL mid,L= 1, R= ((1LL)<<n)-1; char c1,c2; bool flag = true; while(L <= R ){ mid = L+(R-L)/2; printf("%lld\n",mid); cin>>c1; if(c1=='=') break; if(flag){ printf("%lld\n",mid); cin>>c2; if(c2=='=') break; if(c1!=c2){ //error flag = false; char c3; printf("%lld\n",mid); cin>>c3; if(c1==c3){ if(c1=='<') L = mid+1; else R = mid-1; } else{ if(c2=='<') L = mid+1; else R = mid-1; } } else{ if(c1=='<') L = mid+1; else R = mid-1; } } else{ if(c1=='<') L = mid + 1; else R = mid - 1; } } } int main() { #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); freopen("out.txt", "w", stdout); #endif int in; scanf("%lld %lld",&n, &k); if(n==1){ printf("1\n"); return 0; } if(k==1) gao1(); else if(k<=n) gao2(); else gao3(); return 0; }