ECNU3542神奇的魔术(二分交互题)

Posted chenxiaoran666

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ECNU3542神奇的魔术(二分交互题)相关的知识,希望对你有一定的参考价值。

点此看题面

大致题意: 有一个\(1\sim 2^n\)的排列,\(n\le7\),每次交互告诉你有几个位置上的数是正确的,让你在\(1000\)轮以内猜出每个位置上的数。

二分

显然,我们可以通过二分来求解此题。

具体地,我们先把所有位置填满\(1\),然后暴力枚,找到一个位置填上\(2\)使得此时没有一个位置上的数是正确的。

然后接下来,我们枚举\(3\sim2^n\)的每一个数,每次把\(l\sim mid\)这段区间内除不是\(1\)\(2\)的位置外全填上当前数,然后询问当前对的数的个数。

最后我们交换序列中的\(1\)\(2\)即可。

但注意这样次数会超,于是要加上一个小优化,即若当前二分到的区间内全填满了不是\(1\)\(2\)的数,就直接返回\(false\)

代码

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 7
using namespace std;
int n,bit,a[(1<<N)+5],b[(1<<N)+5],g[(1<<N)+5];
I void Print() for(RI i=1;i<=bit;++i) cout<<a[i]<<" ";cout<<endl;//输出交互
I bool Check(CI x,CI tl,CI tr)//检查

    RI i,t,fg=0;for(i=tl;i<=tr;++i) a[i]==b[i]&&(a[i]=x,fg=1);
    if(!fg) return 0;Print(),cin>>t;if(!~t) return 20030909;
    for(i=tl;i<=tr;++i) a[i]==x&&(a[i]=b[i]);return t==x-2;

int main()

    RI i,t=0,l,r,mid;for(cin>>n,bit=1<<n,i=1;i<=bit;++i) a[i]=b[i]=1;bit==2&&(g[1]=1,g[2]=2);
    for(i=1;i<=(bit>>2);++i) g[++t]=(bit>>1)-i+1,g[++t]=(bit>>1)+i,g[++t]=i,g[++t]=bit-i+1;
    for(i=1;i<=bit;++i) if(a[g[i]]=2,Print(),cin>>t,t==0) b[g[i]]=2;break;else a[g[i]]=1;//初始化
    for(i=3;i<=bit;++i)//枚举数
    
        l=1,r=bit;W(l<r) Check(i,l,mid=l+r-1>>1)?r=mid:l=mid+1;//二分
        a[r]=i;//填数
    
    for(i=1;i<=bit;++i) a[i]==1?a[i]=2:a[i]==2&&(a[i]=1);return Print(),0;//输出

以上是关于ECNU3542神奇的魔术(二分交互题)的主要内容,如果未能解决你的问题,请参考以下文章

CF 714D Searching Rectangles 交互题 二分

Codeforces Round #503 (by SIS, Div. 2) D. The hat -交互题,二分

AtCoder Petrozavodsk Contest 001 C - Vacant Seat 交互题带分类讨论的二分

Codeforces 862D. Mahmoud and Ehab and the binary string 二分(交互题)

ACM交互题

[loj #6003]「网络流 24 题」魔术球 二分图最小路径覆盖,网络流