HDU 5269 ZYB loves Xor I 01trie

来源:互联网 发布:深圳网络金融公司 编辑:程序博客网 时间:2024/06/08 08:14

题目:

http://acm.hdu.edu.cn/showproblem.php?pid=5269

题意:

给定一个长度为n的数组, 求(lowbit(AiAj))(i,j[1,n])的和,结果取模998244353

思路:

首先把所有数字倒着插入到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;}