hdu 5269 字典树

题目链接:hdu 5269

ZYB loves Xor I

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 184    Accepted Submission(s): 101


Problem Description
Memphis loves xor very musch.Now he gets an array A.The length of A is n.Now he wants to know the sum of all (lowbit( Ai xor Aj)) (i,j[1,n])
We define that lowbit(x)=2k,k is the smallest integer satisfied ((x and 2k)>0)
Specially,lowbit(0)=0
Because the ans may be too big.You just need to output ans mod 998244353
 

 

Input
Multiple test cases, the first line contains an integer T(no more than 10), indicating the number of cases. Each test case contains two lines
The first line has an integer  n
The second line has n integers A1,A2....An
n[1,5104]Ai[0,229]
 

 

Output
For each case, the output should occupies exactly one line. The output format is Case #x: ans, here x is the data number begins at 1.
 

 

Sample Input
2
5
4 0 2 7 0
5
2 6 5 4 0
 

 

Sample Output
Case #1: 36
Case #2: 40
 
Source

解题思路:异或运算相同为0,不同为1。lowbit函数是找一个数表示成2进制数,从最低位开始第一个不为0的数之前有k个0,则结果为2^k。比如2,4。

2:010

4:100

我们发现(右数,最右边为第0位)从第0位开始起,他们第1位不同,所以我们可以判断第1位之前都为0,那么lowbit值为2^1.

所以我们可以建立一个字典树,每一位进行比较,来查询一棵树上当前位与要查询数的当前位有多少个不同的数(假如大小为cnt),那么ans就可以加上cnt*(2^k)。

ps:弱渣第一次用c++的类来编写函数,参考kuangbin大神代码,相识度极高,勿喷。弱渣开始用vector存,虽然侥幸ac(至少思路还是对的噻),但还是被大数据hack内存。。。。。

/**************************************************************
    Problem:hdu 5269 ZYB loves Xor I
    User: youmi
    Language: C++
    Result: Accepted
    Time:109MS
    Memory:10636K
****************************************************************/
//#pragma comment(linker, "/STACK:1024000000,1024000000")
//#include<bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <stack>
#include <sstream>
#include <cmath>
#include <queue>
#include <string>
#include <vector>
#define zeros(a) memset(a,0,sizeof(a))
#define ones(a) memset(a,-1,sizeof(a))
#define sc(a) scanf("%d",&a)
#define sc2(a,b) scanf("%d%d",&a,&b)
#define rep(i,n) for(int i=0;i<n;i++)
#define lson (step<<1)
#define rson (lson+1)
#define esp 1e-6
#define oo 0x3fffffff
#define TEST cout<<"*************************"<<endl;

using namespace std;
typedef long long ll;

int n;
const int mod=998244353;
const int maxn=50000+10;
int bit[31];
ll ans;
struct trie
{
    int next[30*maxn][2];
    int tot[maxn*30];
    int cnt,root;
    int newNode()
    {
        tot[cnt]=0;
        next[cnt][0]=next[cnt][1]=-1;
        cnt++;
        return cnt-1;
    }
    void init()
    {
        cnt=0;
        root=newNode();
    }
    void Insert(int val)
    {
        int temp=root;
        int id;
        for(int i=0;i<30;i++)
        {
            if(val&bit[i])
                id=1;
            else
                id=0;
            if(next[temp][id^1]!=-1)//遇到与当前位不同的则直接计算lowbit的值
                ans=(ans+((ll)bit[i]*tot[next[temp][id^1]])%mod)%mod;
            if(next[temp][id]==-1)//如果当前位没有数曾建立过这条路径就建立新的点
                next[temp][id]=newNode();
            temp=next[temp][id];
            tot[temp]++;
        }
    }
}tree;
int main()
{
    //freopen("in.txt","r",stdin);
    int T_T;
    scanf("%d",&T_T);
    bit[0]=1;
    for(int i=1;i<=30;i++)
    {
        bit[i]=bit[i-1]<<1;//这步优化1<<i
    }
    for(int kase=1;kase<=T_T;kase++)/**<  */
    {
        scanf("%d",&n);
        int val;
        ans=0;
        tree.init();
        for(int i=1;i<=n;i++)
        {
            sc(val);
            tree.Insert(val);
        }
        ans=(ans<<1)%mod;//(i,j)/(j,i)相互之间都可以,所以乘以2
        printf("Case #%d: %I64d\n",kase,ans);
    }
    return 0;
}

 

你可能感兴趣的:(HDU)