HDU 6186 CS Course 简单思维题

xiaoxiao2021-02-28  90

题目:

http://acm.hdu.edu.cn/showproblem.php?pid=6186

题意:

给出一个长度为n的数组a,对于每次询问,给出一个数字p,意为去掉数字a[p],然后求数组中其余n-1个数字的按位与,按位或,按位异或。

思路:

首先把每个数字化成二进制记录每个位置上0、1的个数,对于询问,计算出a[p]二进制中每个位置上0、1的个数。对于按位与,从二进制角度看,只要当前位置上有一个0,那么当前位置的值就是0,对于按位或,只要当前位置上有一个1,那么当前位置的值就是1。而按位异或,首先求出所有数字的按位异或,再与a[p]异或一下,就可以了

#include <bits/stdc++.h> using namespace std; const int N = 100000 + 10, INF = 0x3f3f3f3f; int a[N]; int num1[35], num0[35], tmp1[35], tmp0[35]; int len = 31; void work(int x, int num1[], int num0[]) { for(int i = len-1; i >= 0; i--) { int j = 1 & (x >> i); if(j) num1[i]++; else num0[i]++; } } int main() { int n, m; while(~ scanf("%d%d", &n, &m)) { memset(num0, 0, sizeof num0); memset(num1, 0, sizeof num1); int _xor = 0; for(int i = 1; i <= n; i++) { scanf("%d", &a[i]); work(a[i], num1, num0); _xor ^= a[i]; } int p; for(int i = 1; i <= m; i++) { scanf("%d", &p); memset(tmp0, 0, sizeof tmp0); memset(tmp1, 0, sizeof tmp1); work(a[p], tmp1, tmp0); int ans1 = 0; for(int j = len-1; j >= 0; j--) if(num0[j] - tmp0[j] == 0 && num1[j] - tmp1[j] != 0) ans1 = ans1 * 2 + 1; else ans1 = ans1 * 2 + 0; int ans2 = 0; for(int j = len-1; j >= 0; j--) if(num1[j] - tmp1[j] != 0) ans2 = ans2 * 2 + 1; else ans2 = ans2 * 2 + 0; int ans3 = _xor ^ a[p]; printf("%d %d %d\n", ans1, ans2, ans3); } } return 0; }
转载请注明原文地址: https://www.6miu.com/read-53421.html

最新回复(0)