泉州网站建设哪里好,濮阳网吧,指定网站怎么设置路由器只访问,手机制作小程序软件的app正题
题目链接:https://codeforces.com/contest/1556/problem/D 题目大意
现在有nnn个你不知道的数字#xff0c;你有两种询问操作
询问两个下标的数字的andandand询问两个下标的数字的ororor
要求在2n2n2n次操作以内求出第kkk小的数字 1≤n≤104,0≤ai≤1091\leq n\leq 1…正题
题目链接:https://codeforces.com/contest/1556/problem/D 题目大意
现在有nnn个你不知道的数字你有两种询问操作
询问两个下标的数字的andandand询问两个下标的数字的ororor
要求在2n2n2n次操作以内求出第kkk小的数字
1≤n≤104,0≤ai≤1091\leq n\leq 10^4,0\leq a_i\leq 10^91≤n≤104,0≤ai≤109 解题思路
显示我们取andandand之后为000且ororor之后为111的位就可以得到两个数字的异或所以我们可以通过2n−22n-22n−2次询问得到所有数字之间的异或值那么此时我们就只需要知道一个数字就可以得到其他所有的。
然后考虑怎么求某一个数字我们前面的步骤中拿111去ororor和andandand其他所有的值不难发现每次我们除了知道异或值还能确定这两个数字异或之后为000的位上的具体值。
那么我们不知道位的肯定是111和其他所有数字都不同的也就是这些位上除了111其他数字都相同那么我们直接拿另外两个数and/orand/orand/or一下再取这些位上的值就好了。
这样询问次数就是2n−12n-12n−1次可以通过本题。 code
#includecstdio
#includecstring
#includealgorithm
using namespace std;
const int N1e410;
int n,k,a[N],p[N];
int main()
{scanf(%d%d,n,k);int MS(130)-1,ans0,bns0;for(int i2,x,y;in;i){printf(and 1 %d\n,i);fflush(stdout);scanf(%d,x);printf(or 1 %d\n,i);fflush(stdout);scanf(%d,y);y^MS;p[i](MS^(x|y));ans|x;bns|y;}int cMS^(ans|bns),cns;printf(and 2 3\n);fflush(stdout);scanf(%d,cns);cnsc;a[1](c^cns)|ans;for(int i2;in;i)a[i]a[1]^p[i];sort(a1,a1n);printf(finish %d\n,a[k]);fflush(stdout);return 0;
}