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]);//输出
}
}
}