ZYB loves Xor I HDU - 5269 字典树

题意:

T组样例,给你n个数。你要找出来这n个数中任意两个数的二进制位中  最低位不同  的位置(假设是k),然后让所有2^k加起来就是结果

什么意思?

例如4 和 2

4的二进制是(100),2的二进制是(010),那么它们二进制位中 最低位不同 的位置  就是1,然后把这个2^1加入最后结果就完了

注意:4和2算一次结果,2和4也要算一次结果

 

解释个样例:

5
4 0 2 7 0

sum=0

4和0:k=2,sum+=2^2

4和2:k=1,sum+=2^1

4和7:k=0,sum+=2^0

4和0:k=2,sum+=2^2

0和2:k=1,sum+=2^1

0和7:k=0,sum+=2^0

0和0:因为0^0=0,题目上lowbit(0)=0,所以sum+=0

 

2和7:k=0,sum+=2^0

2和0:k=1,sum+=2^1

7和0:k=0,sum+=2^0

sum=4+2+1+4+2+1+0+1+2+1=18

又因为“4和2算一次结果,2和4也要算一次结果”,所以sum*=2

sum=36

 

题解:

观察发现对于任意一个数 x 来说,只要前 i-1 位和其它数相等,第i位不相等。那么 ans += cnt * pow(2, i-1);
 cnt 为和它前i-1个前缀都相等的数的个数。 可以利用字典树边插入边更新ans,最后ans*2就是答案。

 

数组开小了TLE了半天。。。。

 

代码:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cstdlib>
 5 #include <algorithm>
 6 using namespace std;
 7 typedef long long ll;
 8 const int maxn=2;
 9 const ll mod=998244353;
10 typedef struct Trie* TrieNode;
11 ll v[50005];
12 ll w[31],result;
13 struct Trie
14 {
15     ll val,sum;
16     TrieNode next[2];
17     Trie()
18     {
19         val=0;
20         sum=0;
21         memset(next,NULL,sizeof(next));
22     }
23 };
24 
25 void inserts(TrieNode root,ll x,ll y)
26 {
27     TrieNode p = root;
28     for(ll i=0;i<30;++i)
29     {
30         ll temp=(x>>i)&1;
31         if(p->next[temp]==NULL) p->next[temp]=new struct Trie();
32         if(p->next[!temp]!=NULL && p->next[!temp]->sum>0)
33         {
34             ll t=p->next[!temp]->sum;
35             t=(t*(ll)w[i])%mod;
36             result=(result+t)%mod;
37         }
38         p->next[temp]->sum+=y;
39         p=p->next[temp];
40     }
41     p->val=x;
42 }
43 void Del(TrieNode root)
44 {
45     for(ll i=0 ; i<2 ; ++i)
46     {
47         if(root->next[i])Del(root->next[i]);
48     }
49     delete(root);
50 }
51 
52 int main()
53 {
54     ll t,n,sum=1;
55     int p=0;
56     w[0]=1;
57     for(int i=1;i<=30;++i)
58     {
59         sum=(sum*2)%mod;
60         w[i]=sum;
61     }
62     scanf("%lld",&t);
63     while(t--)
64     {
65         TrieNode root = new struct Trie();
66         scanf("%lld",&n);
67         //ll ans=0;
68         result=0;
69         for(ll i=1;i<=n;++i)
70         {
71             scanf("%lld",&v[i]);
72             inserts(root,v[i],1);
73         }
74         printf("Case #%d: %lld\n",++p,(result<<1)%mod);
75         Del(root);
76     }
77     return 0;
78 }

 

posted @ 2019-12-07 13:23  kongbursi  阅读(184)  评论(0编辑  收藏  举报