Problem Description
输入n,q。代表有n个数,q次访问。每次访问给你一个下标,让你除去这个下标的数后。所有数进行&, |, ^运算的结果,并输出。
思路:
一个数^0这个数还是不变的。一个数^本身,等于0。所以所有数的^在^一次除去的数。就是^的结果。&,|,这个的话,统计一下n个数的二进制0的个数,1的个数。看看他们对结果有没有影响,有影响就改变,没影响就不变。具体实现看代码
#include<bits/stdc++.h> using namespace std; int vis[66]; long long a[100055]; int main() { int n, q, num; long long An, Or, Xor, i, j, Max; while(~scanf("%d %d", &n, &q)) { memset(vis, 0, sizeof(vis)); scanf("%lld", &a[1]); An = Or = Xor = a[1];//求所有数的&|^ Max = a[1];//求最大的数 for(j = 0; j <= 61 && ((long long)1<<j) <= a[1]; j++) { if(((long long)1<<j) & a[1])//记录二进制每一位有多少个1.那么0的个数就是n-(1的个数) { vis[j]++; } } for(i = 2; i <= n; i++) { scanf("%lld", &a[i]); Max = max(Max, a[i]); for(j = 0; j <= 61 && ((long long)1<<j) <= a[i]; j++) { if(((long long)1<<j) & a[i]) { vis[j]++; } } An = An & a[i]; Or = Or | a[i]; Xor = Xor ^ a[i]; } while(q--)//q次访问 { long long x = An, y = Or, z = Xor; scanf("%d", &num); for(j = 0; j <= 61 && ((long long)1<<j) <= Max; j++) { if(((long long)1<<j) & a[num])//如果是1。对&没有影响 { if(vis[j] == 1 && (n - vis[j]))//如果只有一个1,恰好是a[num]提供的。那么y得去掉1变为0 { y = y ^ ((long long)1<<j); } } else//如果是0,对|没有影响 { if(vis[j] && (n - vis[j] == 1))//如果只有一个0,恰好是a[num]提供的。那么x得取掉0变为1 { x = x ^ ((long long)1<<j); } } } printf("%lld %lld %lld\n", x, y, z^a[num]);//输出 } } }