[hdu5269]字典树

题意:给一个序列[a, a + n),求Σlowbit(ai, aj),i,j∈[0,n)。

思路:lowbit与位有关,于是按位统计即可,如果lowbit=2^k,则前k位相同,前缀相同,于是想到用字典树来统计。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#pragma comment(linker, "/STACK:10240000,10240000")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <algorithm>
#include <queue>
using  namespace  std;
 
const  int  maxn = 2e6;
const  int  md =  998244353;
 
struct  Trie {
     int  ch[maxn][2], val[maxn], sz;
     void  init() {
         sz = 1;
         memset (ch, 0,  sizeof (ch));
         memset (val, 0,  sizeof (val));
     }
     void  insert( int  x) {
         int  p = 0, cnt = 0;
         while  (cnt < 31) {
             if  (ch[p][x & 1]) p = ch[p][x & 1];
             else  p = ch[p][x & 1] = sz ++;
             val[p] ++;
             cnt ++;
             x >>= 1;
         }
     }
     int  solve( int  p,  int  dep) {
         int  buf = ( long  long )val[ch[p][0]] * val[ch[p][1]] % md *
                 (( long  long )1 << dep) % md;
         if  (ch[p][0]) buf = (buf + solve(ch[p][0], dep + 1)) % md;
         if  (ch[p][1]) buf = (buf + solve(ch[p][1], dep + 1)) % md;
         return  buf;
     }
};
Trie solver;
int  main() {
#ifndef ONLINE_JUDGE
     freopen ( "in.txt" "r" , stdin);
#endif // ONLINE_JUDGE
     int  T, cas = 0, n;
     cin >> T;
     while  (T --) {
         cin >> n;
         solver.init();
         for  ( int  i = 0; i < n; i ++) {
             int  x;
             scanf ( "%d" , &x);
             solver.insert(x);
         }
         printf ( "Case #%d: %d\n" , ++ cas, solver.solve(0, 1));
     }
     return  0;
}

 

你可能感兴趣的:(HDU)