位运算 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 }

 

posted @ 2015-04-26 10:48  Running_Time  阅读(341)  评论(0编辑  收藏  举报