位运算 ZOJ 3870 Team Formation
1 /*
2 题意:找出符合 A^B > max (A, B) 的组数;
3 位运算:异或的性质,1^1=0, 1^0=1, 0^1=1, 0^0=0;与的性质:1^1=1, 1^0=0, 0^1=0, 0^0=0;
4 假设A < B,一定要满足B的最高位对应A的值是0,这样才可能>B(即0^1=1);
5 然后比赛时假设A的极限是类似0111111的情况,最后假设有误;
6 题解是先把每个数最高位(1)的位置统计个数,1<<4 的意思是 000010000;
7 只要与为0,表示最高位p位置的所有数字和当前a[i]异或一定满足,累加ans;
8
9 位运算不熟悉, '⊕'还是别人告诉我是异或的;
10 详细解释:http://blog.csdn.net/LYHVOYAGE/article/details/45285731
11 */
12 #include <cstdio>
13 #include <algorithm>
14 #include <cmath>
15 #include <iostream>
16 #include <cstring>
17 #include <string>
18 #include <map>
19 #include <set>
20 using namespace std;
21
22 const int MAXN = 1e5 + 10;
23 const int INF = 0x3f3f3f3f;
24 int a[MAXN];
25 int bit[31];
26
27 void solve(int x)
28 {
29 int p = 31;
30 while (p >= 0)
31 {
32 if (x & (1<<p))
33 {
34 bit[p]++; return ;
35 }
36 p--;
37 }
38
39 return ;
40 }
41
42 int main(void) //ZOJ 3870 Team Formation
43 {
44 //freopen ("B.in", "r", stdin);
45
46 int t, n;
47 scanf ("%d", &t);
48 while (t--)
49 {
50 memset (bit, 0, sizeof (bit));
51 scanf ("%d", &n);
52 for (int i=1; i<=n; ++i)
53 {
54 scanf ("%d", &a[i]); solve (a[i]);
55 }
56
57 long long ans = 0;
58 for (int i=1; i<=n; ++i)
59 {
60 int p = 31;
61 while (p >= 0)
62 {
63 if (a[i] & (1<<p)) break;
64 p--;
65 }
66 while (p >= 0)
67 {
68 if (!(a[i] & (1<<p))) ans += bit[p];
69 p--;
70 }
71 }
72
73 printf ("%lld\n", ans);
74 }
75
76 return 0;
77 }
编译人生,运行世界!