binary string codeforces 862D 互動題,二分答案
Mahmoud and Ehab are in the fourth stage now.
Dr. Evil has a hidden binary string of length n. He guarantees that there is at least one '0' symbol and at least one '1' symbol in it. Now he wants Mahmoud and Ehab to find a position of any '0' symbol and any '1' symbol. In order to do this, Mahmoud and Ehab can ask Dr. Evil up to 15
Help Mahmoud and Ehab find these two positions.
You will get Wrong Answer verdict if
- Your queries doesn't satisfy interaction protocol described below.
- You ask strictly more than 15 questions and your program terminated after exceeding queries limit. Please note, that you can do up to 15 ask queries and one answer query.
- Your final answer is not correct.
If you exceed the maximum number of queries, You should terminate with 0, In this case you'll get Wrong Answer, If you don't terminate you may receive any verdict because you'll be reading from a closed stream .
InputThe first line of input will contain a single integer n (2 ≤ n ≤ 1000) — the length of the hidden binary string.
OutputTo print the final answer, print "! pos0 pos1" (without quotes), where pos0 and pos1 are positions of some '0' and some '1' in the string (the string is 1-indexed). Don't forget to flush the output after printing the answer!
InteractionTo ask a question use the format "? s" (without quotes), where s is a query string. Don't forget to flush the output after printing a query!
After each query you can read a single integer from standard input — the Hamming distance between the hidden string and the query string.
To flush the output you can use:-
- fflush(stdout) in C++;
- System.out.flush() in Java;
- stdout.flush() in Python;
- flush(output) in Pascal;
- See the documentation for other languages .
Hacking.
To hack someone just print one binary string with length up to 1000, containing at least one '0' and at least one '1'.
Example input3 2 1 3 2 1 0output
? 000 ? 001 ? 010 ? 011 ? 100 ? 101 ! 2 1題解:
猜測到詢問次數15與序列長度1000之間是指數關係,即2的指數。直接想到二分搜尋的方法。
題目保證至少1個0和1個1。說明一定可以找到01串或者是10串。
我們的目的就是找到這樣的長度為2的串。
怎麼做?
二分!
我們第一次詢問n個0組成的串,得到回覆req後,req表示的就是串中1的個數,記為num1 = req。
然後我們定義區間L = 0,R = n表示我們要當前的區間。
mid = (L + R) / 2;
判斷[mid,R]中是否既有0又有1。如果是那麼L = mid
否則R = mid。
這樣一隻減少,直到[L,R]區間長度為2 停止。
現在問題變成了,怎麼判斷一個區間裡面既有0又有1呢?
我們這樣考慮如果一個區間裡面全是0的話,那麼我們構造一個序列使得只有區間[L,R]裡面全是1,其他地方全是0,這樣的詢問的話,返回值req = num1 + (R-L+1)
而如果區間裡面全是1的話,那麼我們構造一個序列使得只有區間[L,R]裡面全是1,其他地方全是0,這樣的詢問的話,返回值req = num1 - (R-L+1)
因此,如果區間[L,R]裡面既有0又有1的話,我們構造一個序列使得只有區間[L,R]裡面全是1,其他地方全是0,這樣的詢問的話,返回值num1 - (R-L+1 < req < num1 + (R-L+1)
至此此題就解決了。
程式碼:
#include <bits/stdc++.h>
using namespace std;
int black = 0;
int n;
bool check(int L,int R){
printf("? ");
for(int i = 1;i < L;i++) {
printf("%d",0);
}
for(int i = L;i <= R;i++) {
printf("%d",1);
}
for(int i = R+1;i <= n;i++){
printf("%d",0);
}
puts("");
fflush(stdout);
int req;
scanf("%d",&req);
if(black - (R - L + 1) < req && req < black + (R - L + 1)){
//if(req == black + R - L + 1){
//yes
return true;
}
else{
return false;
}
}
int pos1,pos0;
int main(){
scanf("%d",&n);
printf("? ");
for(int i = 1;i <= n;i++){
printf("%d",0);
}
puts("");
fflush(stdout);
scanf("%d",&black);
int L = 1,R = n;
while(R - L >= 2){
int mid = (R + L) / 2;
if(check(mid,R)){
L = mid;
}
else{
R = mid;
}
}
printf("? ");
for(int i = 1;i < L;i++){
printf("%d",0);
}
printf("1");
for(int i = L+1;i <= n;i++){
printf("%d",0);
}
puts("");
fflush(stdout);
int req;
scanf("%d",&req);
printf("! ");
if(req < black){
cout<<R<<' '<<L<<endl;
}
else{
cout<<L<<' '<<R<<endl;
}
fflush(stdout);
return 0;
}