HDU 5269 ZYB loves Xor I( 01 Trie 树)

题目链接:传送门

题意:

for i: 1~n  forj:1~n lowbit(a[i]^a[j])
lowbit(x)表示取x的最低位1。

lowbit(3)=1    lowbit(6)=2;

分析:

因为其中有一个异或运算,我们就先来分析这个异或运算。发现如果lowbit(x^y) = 2^p;

那么把x^y转化成2进制后他们的前p-1位一定是相同的。那么思路就来了把所有的数字转换

成01字符串,注意要使他们的长度都相等,然后建一颗trie树。然后遍历的时候如果同时

有左右孩子的话那么ans = ans(ans + l_num*r_num)%mod;最后的ans还要乘以2.

代码如下:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#define PB push_back
#define MP make_pair
#define REP(i,n) for(int i=0;i<(n);++i)
#define FOR(i,l,h) for(int i=(l);i<=(h);++i)
#define DWN(i,h,l) for(int i=(h);i>=(l);--i)
#define IFOR(i,h,l,v) for(int i=(h);i<=(l);i+=(v))
#define CLR(vis) memset(vis,0,sizeof(vis))
#define MST(vis,pos) memset(vis,pos,sizeof(vis))
#define MAX3(a,b,c) max(a,max(b,c))
#define MAX4(a,b,c,d) max(max(a,b),max(c,d))
#define MIN3(a,b,c) min(a,min(b,c))
#define MIN4(a,b,c,d) min(min(a,b),min(c,d))
#define PI acos(-1.0)
#define INF 1000000000
#define LINF 1000000000000000000LL
#define eps 1e-8
#define LL long long
using namespace std;

const LL mod = 998244353;

const int maxn =5e4+10;

LL a[maxn];

const int max_size = 2;

int id(char c){
    return c-'0';
}

struct Trie{
    Trie *ch[2];
    LL num;
    Trie(){
        num = 0;
        for(int i=0;i<max_size;i++)
            ch[i]=NULL;
    }
};

void insert_str(Trie *root,char *s){
    Trie *p = root;
    for(int i=0; p&&s[i] ; i++){
        int u = id(s[i]);
        if(p->ch[u]==NULL)
            p->ch[u] = new Trie;
        p=p->ch[u];
        p->num++;
        //cout<<"***"<<p->num<<endl;
    }
}

LL ans;
void dfs(Trie *ff,LL dept){
    Trie *p = ff;
    if(p->ch[0]!=NULL&&p->ch[1]!=NULL){
        ans=(ans+(p->ch[0]->num*p->ch[1]->num)%mod*((1LL<<dept)%mod))%mod;
    }
    if(p->ch[0]!=NULL)
        dfs(p->ch[0],dept+1);
    if(p->ch[1]!=NULL)
        dfs(p->ch[1],dept+1);
    return ;
}

inline LL read()
{
    LL x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}

int main()
{
    LL n,t;
    int cas=1;
    t=read();
    char s[50];
    while(t--){
        Trie *root = new Trie;
        n=read();
        REP(i,n) a[i]=read();
        ans = 0;
        REP(i,n){
            int cnt = 0;
            LL tmp =a[i];
            while(tmp){
                s[cnt++]=tmp%2+'0';
                tmp/=2;
            }
            FOR(i,cnt,40) s[i]='0';
            s[41]=0;
            insert_str(root,s);
        }
        dfs(root,0);
        printf("Case #%d: %I64d\n",cas++,(ans<<1)%mod);
    }
    return 0;
}
时间: 2024-07-29 05:12:08

HDU 5269 ZYB loves Xor I( 01 Trie 树)的相关文章

hdu 5269 ZYB loves Xor I(字典树)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5269 思路分析:当lowbit(AxorB)=2p 时,表示A与B的二进制表示的0-p-1位相等,第p位不同:考虑维护一棵字母树,将所有数字 转换为二进制形式并且从第0位开始插入树中,并在每个节点中记录通过该结点的数字数目:最后统计答案,对于每一个数字, 对于在其路径中的每一个结点X,假设其为第K层,统计通过与该结点不同的值的结点的数目count,则结果增加count*2k; 代码如下: #incl

hdu 5269 ZYB loves Xor I(计数

题意:给出n个数,n个数两两异或后的最后一个bit位k,求所有2^k的和. 比赛的时候递归写挂了....痛心啊...后来看了半天结果把一个数组移到函数体里就1a了(递归的时候覆盖了...)T_T. 思路是这样的:如果最后一位不相同,那么他们异或结果的最后一位与二者最后一位较低的相同,那么把这些数字按最后一位的位置分为若干组,然后不同组可以直接相乘.相同组因为最后一位相同,所以异或的结果与最后一位无关,把最后一位去掉然后递归处理这一组.因为一共有30位,数组长度为n,复杂度大概是O(30*n).

hdu 5269 ZYB loves Xor I

今晚best code第二题 好好学了下字典树,确实自己会的东西实在太少了 #include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstdlib> #include<queue> #include<map> #include<stack> #include<list> #include<

【HDU】5269 ZYB loves Xor I

[算法]trie [题解] 为了让数据有序,求lowbit无法直接排序,从而考虑倒过来排序,然后数据就会呈现出明显的规律: 法一:将数字倒着贴在字典树上,则容易发现两数的lowbit就是它们岔道结点的深度,所以先建树后对于一个数字依次把每次分岔开的另一边的size乘上权值累加答案. 法二:从高位到低位分组求和,即第一位1在上,0在下,则两边之间互相计算过后就再无影响,只剩下各自内部的事情再处理.由于排序后数据的有序性使分治可行. 法三:排序后对于一个数字,它和后面的数字的lowbit有单调性--

bestcoder r44 p3 hdu 5270 ZYB loves Xor II

这是昨晚队友跟我说的题,不知道当时是什么玄幻的事件发生了,,我看成了两两相乘的XOR 纠结了好长时间间 不知道该怎么办 今天早上看了下这道题,发现是两两相加的XOR  然后就想了想昨晚的思路 发现可做 对于 XOR 在我的记忆中 ,大部分的都是拆成数位来做 那么这题  .... 其实也是类似的 拆成数位.有两种拆法  将数据拆成数位和将答案拆成数位(其实就是考虑答案的每一位) 想了想将数据拆成数位·········· 没法单独考虑每一位的‘功’ 那就将考虑答案的每一位了 最好考虑的是第一位了 只

hdu5269 ZYB loves Xor I 异或,字典树

hdu5269  ZYB loves Xor I   异或,字典树 ZYB loves Xor I Accepts: 142 Submissions: 696 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) 问题描述 ZYB喜欢研究Xor,现在他得到了一个长度为nn的数组A.于是他想知道:对于所有数对(i,j)(i \in [1,n],j \in [1,n])(i,j)(i∈[1,n

HDU 11488 Hyper Prefix Sets (字符串-Trie树)

H Hyper Prefix Sets Prefix goodness of a set string is length of longest common prefix*number of strings in the set. For example the prefix goodness of the set {000,001,0011} is 6.You are given a set of binary strings. Find the maximum prefix goodnes

HDU 5269 &amp;&amp; BestCoder #44 1002 ZYB loves Xor I (分治)

题目地址:HDU 5269 比赛的时候想到了分治的思路,但是脑残了.,.写麻烦了...调了好久也没调出来..(分治写的太少..)赛后优化了一下..就过了.. 我的思路是先排序,排序是按照的将每个数字的二进制表示倒过来的字典序从大到小排,比如样例2中的2,6,5,4,0,二进制分别是010,110,101,100,000,排序之后是 101 110 010 100 000 这样的话就把后缀相同的都给放在一块了.其实也相当于字典树,不过比赛的时候没想到字典树,只想到了分治.. 然后从末位开始找,对所

hdu 5268 ZYB loves Score 水题

ZYB loves Score Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5268 Description One day,ZYB participated in the BestCoder Contest There are four problems. Their scores are 1000,1500,2000,2500 According to the r