当前位置: 代码迷 >> 综合 >> 字典树 hdu5269 ZYB loves Xor I
  详细解决方案

字典树 hdu5269 ZYB loves Xor I

热度:52   发布时间:2023-12-14 04:17:07.0

把每个数字按照低位在前高位在后插入到字典树中

那么从低位开始,根节点的左边代表0,右边代表1,如果左右两边都有,那么就是左边的数量*右边的数量*F[cnt]

然后对左边和右边分治就可以得到答案了


#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<queue>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long LL;
const int MX=50000+5;
const LL mod=998244353;LL F[MX];
struct Trie{int sum;Trie *Nxt[2];Trie(){sum=0;Nxt[0]=Nxt[1]=NULL;}
};void Trie_add(Trie*root,int x){for(int i=0;i<=31;i++){int w=((x&(1<<i))!=0);if(root->Nxt[w]==NULL){root->Nxt[w]=new Trie();}root=root->Nxt[w];root->sum++;}
}void init(){for(int i=0;i<=31;i++){F[i]=1LL<<i;}
}LL solve(Trie*root,int cnt){LL ret=0,l,r;if(root->Nxt[0]==NULL) l=0;else{l=root->Nxt[0]->sum;ret=(ret+solve(root->Nxt[0],cnt+1))%mod;}if(root->Nxt[1]==NULL) r=0;else{r=root->Nxt[1]->sum;ret=(ret+solve(root->Nxt[1],cnt+1))%mod;}ret+=l*r*F[cnt]%mod;return ret;
}int main(){int T,n,t,ansk=0;scanf("%d",&T);init();while(T--){scanf("%d",&n);Trie *root=new Trie();for(int i=1;i<=n;i++){scanf("%d",&t);Trie_add(root,t);}printf("Case #%d: %I64d\n",++ansk,solve(root,0)*2%mod);}return 0;