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

 

你可能感兴趣的:(format)