题目:
http://acm.hdu.edu.cn/showproblem.php?pid=5269
题意:
给定一个长度为
n
的数组, 求
思路:
首先把所有数字倒着插入到 trie 中,然后查询每个数字和所有数字的异或再 lowbit ,在 trie 上查询的思路好像说不好,就不说了,被取模坑了两次,没看到。。。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 50000 + 10, M = 2, INF = 0x3f3f3f3f, mod = 998244353;
struct node
{
node *next[M];
int val;
void init()
{
memset(next, 0, sizeof next);
val = 0;
}
}trie[N*30], *root;
int tot;
int len = 29;
int cas = 0;
int a[N];
node* new_node()
{
trie[tot].init();
return trie + tot++;
}
void trie_init()
{
tot = 0;
root = new_node();
}
void trie_insert(int x)
{
node *p = root;
for(int i = 0; i <= len-1; i++)
{
int j = 1 & (x >> i);
if(p->next[j] == NULL) p->next[j] = new_node();
p->next[j]->val++;
p = p->next[j];
}
}
ll trie_query(int x)
{
node *p = root;
ll ans = 0;
for(int i = 0; i <= len-1; i++)
{
int j = ! (1 & (x >> i));
if(p->next[j]) ans += p->next[j]->val * (1LL << i);
p = p->next[!j];
}
return ans;
}
int main()
{
int t, n;
scanf("%d", &t);
while(t--)
{
trie_init();
scanf("%d", &n);
for(int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
trie_insert(a[i]);
}
ll ans = 0;
for(int i = 1; i <= n; i++) ans += trie_query(a[i]);
printf("Case #%d: %lld\n", ++cas, ans % mod);
}
return 0;
}