2 5 4 0 2 7 0 5 2 6 5 4 0
Case #1: 36Case #2: 40当A xor B 的答案为2p 时,A 和B 表示成二进制数后末p?1 位肯定相同 于是我们维护一颗字母树,将每个数表示成二进制数后翻转可以下,插入字母树 统计答案时,我们找出Ai 的二进制数翻转后在字母树上的路径,对于路径上每个点x ,设他走的边是v ,且当前为第k 位,则和他xor 后lowbit为2k 的数的个数为trans(x,v^1)的子树大小。 trans(x,v)表示字母树上在结点x,走连出去的字母为v的边到达的结点// // main.cpp // bc44_B // // Created by Fangpin on 15/6/13. // Copyright (c) 2015年 FangPin. All rights reserved. // #include <iostream> #include <cstdio> #include <cstring> using namespace std; struct Trie{ int v; Trie *next[2]; Trie(){next[0]=next[1]=NULL;v=1;} }*rt; const int M=998244353; void build(){ rt=new Trie; } int a[31],f[31]; long long ans=0; void insert(){ Trie *p=rt,*q; for(int i=0;i<31;++i){ if(p->next[a[i]^1]!=NULL) ans=(ans+p->next[a[i]^1]->v*f[i])%M; if(p->next[a[i]]==NULL){ q=new Trie; p->next[a[i]]=q; p=q; } else{ p=p->next[a[i]]; ++p->v; } } } void solve(Trie *root){ for(int i=0;i<2;++i){ if(root->next[i]!=NULL) solve(root->next[i]); } delete root; } void init(){ f[0]=1; for(int i=1;i<31;++i){ f[i]=f[i-1]<<1; } } int main(int argc, const char * argv[]) { // insert code here... int t; init(); cin>>t; for(int ca=1;ca<=t;++ca){ int n; scanf("%d",&n); build(); ans=0; for(int i=0;i<n;++i){ int tem; scanf("%d",&tem); for(int j=0;j<31;++j){ a[j]=(tem>>j)&1; } insert(); } solve(rt); cout<<"Case #"<<ca<<": "<<(ans*2)%M<<endl; } return 0; }
原文地址:http://blog.csdn.net/fangpinlei/article/details/46485619