zoukankan      html  css  js  c++  java
  • HDU 5269 ZYB loves Xor I Trie树

    题目链接:

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

    bc:http://bestcoder.hdu.edu.cn/contests/contest_chineseproblem.php?cid=603&pid=1002

    题解:

      (以下有提到位数的都是指二进制表示)

      对于xor值为1的两个数,他们的最低位(二进制表示)必然不同,所以我们把n个数按最低位数不同分为两堆,这两堆个数的乘积就是xor的值等于1的贡献。同理,我们可以递归处理出xor值等于2,4,8,16...2^30的贡献值,然后把它们加起来。

      一种做法是类似快速排序先按最低位数排序,0的在左边,1的在右边,算完2^0的贡献之后,再递归算全0的那块,全1的那块中2^1的贡献,依次类推。不过这种做法的缺陷是最坏情况下时间复杂度会变为n^2;

      一种高效的做法是用一颗trie树来维护,把每个数从最低位开始按每一位的01取值存到trie树上,这样某一位为零的都会在左子树上,为1的都会在右子树上。这样离线处理好就不用我们每一次递归的时候去维护了.

    代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring> 
     4 using namespace std;
     5 
     6 const int maxn=50000+10;
     7 const int mod=998244353;
     8 typedef long long LL;
     9 
    10 struct Trie{
    11     int ch[maxn*33][2],tot;
    12     int val[maxn*33];
    13     void init(){
    14         val[0]=0;
    15         memset(val,0,sizeof(val));
    16         memset(ch[0],0,sizeof(ch[0]));
    17         tot=1;
    18     }
    19     void insert(int x){
    20         int p=0;
    21         for(int i=0;i<30;i++){
    22             int tmp;
    23             if((1<<i)&x) tmp=1;
    24             else tmp=0;
    25             if(!ch[p][tmp]){
    26                 memset(ch[tot],0,sizeof(ch[tot]));
    27                 ch[p][tmp]=tot++;
    28             }
    29             p=ch[p][tmp];
    30             val[p]++;
    31         }
    32     }
    33     void query(int cur,int h,LL &ans){
    34         int lef=ch[cur][0],rig=ch[cur][1];
    35         LL tmp=(LL)val[lef]*val[rig]%mod*(1<<h)%mod;
    36 //        printf("tmp:%d
    ",tmp);
    37         ans+=tmp;
    38         ans%=mod;
    39         if(lef) query(lef,h+1,ans);
    40         if(rig) query(rig,h+1,ans);
    41     }
    42 }trie;
    43 
    44 int n;
    45 
    46 void init(){
    47     trie.init();
    48 }
    49 
    50 int main(){
    51     int tc,kase=0;
    52     scanf("%d",&tc);
    53     while(tc--){
    54         init();
    55         scanf("%d",&n);
    56         for(int i=0;i<n;i++){
    57             int x;
    58             scanf("%d",&x);
    59             trie.insert(x);
    60         }
    61 //        for(int i=0;i<22;i++) printf("val:%d
    ",trie.val[i]); 
    62         LL ans=0;
    63         trie.query(0,0,ans);
    64         printf("Case #%d: %lld
    ",++kase,ans*2%mod);
    65     }
    66     return 0;
    67 }
  • 相关阅读:
    postman设置页面详解
    postman安装使用
    测试入门1:黑盒测试用例设计方法
    oo第十六次作业
    oo第三单元总结
    OO第二单元总结
    select语句
    MySQL数据库基础操作
    创建和查看数据库
    认识MySQL数据库
  • 原文地址:https://www.cnblogs.com/fenice/p/5378703.html
Copyright © 2011-2022 走看看