CF1451 E1交互题

先简单描述一下题意,有一串整数序列a,a的数都是隐藏起来的,可以对a询问ai与aj或,与,异或的结果,最多询问n+2次,试求出a

 

这道题的读入是交互式的,因为没有做过交互题,所以打的时候完全不知道怎么下手

第二天补了一下这道题,看了眼交互怎么写,这里先记录一下:

交互题读入:

每一次询问之后执行

fflush(stdout);然后再读入需要的数据
 
然后是这道题的做法:
因为题目里给出了一个n+2这个数字,非常的耐人寻味,我们知道如果其中一个数是确定的,那么其他数只要用这个数和异或就可以求得
所以理所当然地想到(当然后面发现想歪来)是不是用掉3次来确定一个数,然后再求出其他数
思考了1个多小时后发现显然没有这么妙的方法,正确的其实是(n-3)+5,也就是说我们先使用5次来求出三个数,然后随便挑一个去异或求其他的。
5次位运算求三个数的求解:
首先我们要求x=a1+a2,y=a1+a3,z=a2+a3,如果求得这些,那么解方程就行了。
所以问题就变成了用位运算求a1+a2,那么先使用一次与运算,结果的二进制位为1的地方,说明两个都是1,然后做一次异或,结果的二进制位为1的地方说明一个是1,那么a1+a2=a1&a2*2+a1^a2;
所以一共需要6次运算,3次与3次异或,但是其中一个异或的解可以由另两个得到
所以只要五次。求解完毕
 
下附代码:
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int res[2000005];
 4 int main(){
 5     int n,a,b,c,d,e,f;
 6     scanf("%d",&n);
 7     printf("AND 1 2\n");
 8     fflush(stdout);
 9     scanf("%d",&a);
10     printf("AND 2 3\n");
11     fflush(stdout);
12     scanf("%d",&b);
13     printf("AND 1 3\n");
14     fflush(stdout);
15     scanf("%d",&c);
16     printf("XOR 1 2\n");
17     fflush(stdout);
18     scanf("%d",&d);
19     printf("XOR 1 3\n");
20     fflush(stdout);
21     scanf("%d",&e);
22     f=e^d;
23     int x=a*2+d,y=c*2+e,z=b*2+f;
24     res[1]=(x+y-z)/2;
25     res[2]=(x+z-y)/2;
26     res[3]=(y+z-x)/2;
27     for (int i=4; i<=n; i++){
28         int x;
29         printf("XOR 1 %d\n",i);
30         fflush(stdout);
31         scanf("%d",&x);
32         res[i]=x^res[1];
33     }
34     printf("!");
35     for (int i=1; i<=n; i++)
36         printf(" %d",res[i]);
37     fflush(stdout);
38     return 0;
39 }
View Code

 

posted @ 2020-11-22 13:47  我是菜狗QAQ  阅读(152)  评论(0编辑  收藏  举报