HDU--5269 ZYB loves Xor I (字典树)

题目传送门

在这里插入图片描述
又是一道字典树,,
题目大意
给你了n个数,然后让你求对于所有的i和j,lowbit(a[i]异或a[j])之和。
思路
如果要是学过树状数组,应该对lowbit()不陌生了,lowbit(x)它就是求x二进制下的最低一位不为0的数,比如lowbit(4)=2;lowbit(5)=1;lowbit(16)=8;
异或就不用说了,lowbit(a[i]异或a[j]),就是比较a[i]和a[j]二进制下从后往前的相同的位数,那么我们就可以建一个字典树(二进制从后往前建树),记录每个节点的个数。

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;
const int N=50000+10;
int s[N];
struct zxc
{
    int num;
    int a[2];
}tree[35*N];
int numm;
long long ans=0;
int mod=998244353;
int n;
void init(int x)
{
    tree[x].num=0;
    tree[x].a[0]=-1;
    tree[x].a[1]=-1;
}
void bulid(int x)
{
    int u=0;
    int c;
    for(int i=0;i<30;i++,x/=2)
    {
        c=x&1;
        if(tree[u].a[c]==-1)
        {
            tree[u].a[c]=numm++;
             u=tree[u].a[c];
             init(u);
        }
        else
        {
             u=tree[u].a[c];
        }
        tree[u].num++;
    }


}
long long fin(int x)
{
    int u=0;
    long long tot=0;
    int q=1;
    int c;
    for(int i=0;i<30;i++,q*=2,x/=2)
    {
        c=x&1;
        tot=(tot+tree[tree[u].a[c^1]].num*q%mod)%mod;
        u=tree[u].a[c];
    }
    return tot;
}
int main()
{
    int t;
    int w=1;
    scanf("%d",&t);
    while(t--)
    {
        init(0);
        numm=1;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
          scanf("%d",&s[i]);
          bulid(s[i]);
        }

   ans=0;
    for(int i=1;i<=n;i++)
    {
        ans+=fin(s[i]);
        ans%=mod;
    }
    printf("Case #%d: %lld\n",w++,ans);
    }
    return 0;
}
发布了42 篇原创文章 · 获赞 5 · 访问量 930

猜你喜欢

转载自blog.csdn.net/qq_43402296/article/details/103886487
今日推荐