• 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
    ",kase,ans);
        }
        return 0;
    }
    不为失败找借口,只为成功找方法
  • 相关阅读:
    【BZOJ1046】[HAOI2007]上升序列
    【BZOJ1045】[HAOI2008]糖果传递
    【BZOJ1044】[HAOI2008]木棍分割
    【BZOJ1041】[HAOI2008]圆上的整点
    【LG2257】YY的GCD
    【BZOJ1018】[SHOI2008]堵塞的交通
    【LG4735】最大异或和
    【POJ2182】Lost Cows
    【POJ2482】Stars in Your Window
    【POJ1733】Parity game
  • 原文地址:https://www.cnblogs.com/youmi/p/4574662.html
Copyright © 2020-2023  润新知