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次异或,但是其中一个异或的解可以由另两个得到
所以只要五次。求解完毕
下附代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }