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 }

 

posted @ 2015-06-13 22:45  justPassBy  阅读(238)  评论(0编辑  收藏  举报