binary string codeforces 862D 交互题,二分答案

来源:互联网 发布:淘宝联盟省钱购买 编辑:程序博客网 时间:2024/06/06 02:26

D. Mahmoud and Ehab and the binary string
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

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 questions. They tell Dr. Evil some binary string of length n, and Dr. Evil tells the Hamming distance between these two strings. Hamming distance between 2 binary strings of the same length is the number of positions in which they have different symbols. You can find the definition of Hamming distance in the notes section below.

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.
You will get Idleness Limit Exceeded if you don't print anything or if you forget to flush the output, including for the final answer (more info about flushing output below).

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 .

Input

The first line of input will contain a single integer n (2 ≤ n ≤ 1000) — the length of the hidden binary string.

Output

To 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!

Interaction

To 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
input
3213210
output
? 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){//yesreturn 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;}


原创粉丝点击