bestcoder44#1002
这题采用分治的思想
首先,根据最后一位是否为1,将数分为两个集合, 集合与集合之间的lowbit为1,
然后将每个集合内的元素,倒数第二位是否为1,将数分为两个集合,集合与集合之间的lowbit为2
以此类推。
首先为什么要将数组进行排序,排序的规则是根据数字二进制数,从右到左,第一个不同的数字进行排序,0左,1右
1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 #include <algorithm> 5 #include <iostream> 6 #include <queue> 7 #include <stack> 8 #include <vector> 9 #include <map> 10 #include <set> 11 #include <string> 12 #include <math.h> 13 using namespace std; 14 #pragma warning(disable:4996) 15 typedef long long LL; 16 const int INF = 1<<30; 17 /* 18 19 */ 20 const int MOD = 998244353; 21 int a[50000 + 10]; 22 LL ans; 23 bool cmp(LL a, LL b) 24 { 25 while (a || b) 26 { 27 if ((a & 1) != (b & 1)) 28 return (a & 1) < (b & 1); 29 a >>= 1; 30 b >>= 1; 31 } 32 return false; 33 } 34 35 void dfs(int from, int to, int pos) 36 { 37 if (pos>30) return; 38 if (from > to) return; 39 int i; 40 for ( i = from; i <= to; ++i) 41 { 42 //找到集合的分割点 43 if (a[i] & (1 << pos)) 44 break; 45 } 46 ans = ans + (i - from)*(to - i + 1)*(1 << pos) % MOD; 47 //递归求解分割出来的两个集合 48 dfs(from, i - 1, pos + 1); 49 dfs(i, to, pos + 1); 50 } 51 int main() 52 { 53 int t, n, i; 54 scanf("%d", &t); 55 for (int k = 1; k <= t; ++k) 56 { 57 scanf("%d", &n); 58 for (i = 0; i < n; ++i) 59 { 60 scanf("%d", &a[i]); 61 } 62 ans = 0; 63 sort(a, a + n,cmp); 64 dfs(0, n - 1, 0); 65 ans = ans * 2 % MOD; 66 printf("Case #%d: %d\n",k, ans); 67 } 68 return 0; 69 }