zoukankan      html  css  js  c++  java
  • CF1364E X-OR

    蒟蒻的第一道正式交互题QWQ。

    首先我们要明确一点:如果知道了排列中 (0) 的位置,所有其他位置均可以通过一次询问求出。所以我们的思路是首先找到 (0) 的位置。

    考虑一个暴力的判断一个位置 (x) 是否是 (0) 的方法:

    1. 随机出 30个值域在([0,n-1])范围内的数,记作 (a) 序列
    2. (res=2047),然后依次 (res&=Query(a[i],x))
    3. 若任何时刻 (res=0),则立刻判断 (x) 位置为 (0),若最后 (res) 都不为 (0),则可以大致判断 (x) 位置不为 (0)

    (其中 (Query) 为对交互库的询问,上面算法在很大的概率上是正确的)

    但显然我们不能对每个位置依次判断其是否为 (0)

    但我们可以很快的排除不是 (0) 的位置。

    给你三个位置 (a,b,c)(Query(a,b)) 的答案 (now)

    1. (Query(a,c)<now),则 (b) 位置处不为 (0)
    2. (Query(a,c)>now),则 (c) 位置处不为 (0)
    3. (Query(a,c)=now),则 (a) 位置处不为 (0)

    其中对1.2.的解释是 (0) 位置和任何位置的 (Query) 都为 (0),是不可能大于一个其他的 (Query) 的,对3.的解释是因为你要猜的数列是一个排列,所以 (b eq c),所以显然 (a) 也不能为 (0)

    上述流程可以对任意三个位置通过一次询问排除一个位置是 (0) 的可能性,这也就告诉我们,在进行 (n-2) 次询问后,只有 (2) 个位置可能为 (0),这时我们在使用最上面的暴力判断方法,就可以在很少次数内找到 (0) 的位置,这道题就做完了。

    代码:

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<ctime>
    
    using namespace std;
    
    const int N=3000;
    int n,p[N],ans[N];
    
    int Get(int x,int y)
    {
    	printf("? %d %d
    ",x,y);
    	fflush(stdout);
    	int k;
    	scanf("%d",&k);
    	return k;
    //	return p[x]|p[y];
    }
    
    void init()
    {
    	scanf("%d",&n);
    }
    
    bool check(int x)
    {
    	int A=2047;
    	for (int _=1;_<=30;_++)
    	{
    		int tmp=rand()%n+1;
    		while(tmp==x) tmp=rand()%n+1;
    		A&=Get(x,tmp);
    		if(A==0) return 1;
    	}
    	return 0;
    }
    
    void prework()
    {
    	n=rand()%10+1;
    	while(n<3) n=rand()%10+1;
    	for (int i=1;i<=n;i++)
    		p[i]=i-1;
    	random_shuffle(p+1,p+1+n);
    	printf("%d
    ",n);
    	for (int i=1;i<=n;i++)
    		printf("%d ",p[i]);puts("");
    }
    
    void work()
    {
    	int A=1,B=2,now=Get(A,B);
    	for (int i=3;i<=n;i++)
    	{
    		int C=Get(A,i);
    		if(C<now) B=i,now=C;
    		else if(C==now) A=i,now=Get(A,B);
    	}
    	int pos=check(A)?A:B;
    	for (int i=1;i<=n;i++)
    		if(i!=pos)
    			ans[i]=Get(pos,i);
    	printf("! ");
    	for (int i=1;i<n;i++)
    		printf("%d ",ans[i]);
    	printf("%d
    ",ans[n]);
    	fflush(stdout);
    }
    
    int main()
    {
    	srand(time(0));
    //	prework();
    	init();
    	work();
    	return 0;
    }
    
    由于博主比较菜,所以有很多东西待学习,大部分文章会持续更新,另外如果有出错或者不周之处,欢迎大家在评论中指出!
  • 相关阅读:
    clickhouse 多数据源
    maven-dependency-plugin maven-assembly-plugin
    maven shade plugin
    远程服务器,无法复制粘贴 (通过mstsc复制粘贴失败需要重新启动RDP剪切板监视程序rdpclip.exe)
    Mysql导入大sql文件方法
    MySQL5.7更新json类型字段中的某个key的值 函数json_replace()
    mysq json类型
    增强mybatis-plus的typeHandler,可以支持List<T> 中嵌套对象
    Windows中查看端口占用及关闭对应进程
    Hibernate中继承体现
  • 原文地址:https://www.cnblogs.com/With-penguin/p/13193502.html
Copyright © 2011-2022 走看看