【HDU】5269 ZYB loves Xor I

【算法】trie

【题解】

为了让数据有序,求lowbit无法直接排序,从而考虑倒过来排序,然后数据就会呈现出明显的规律:

法一:将数字倒着贴在字典树上,则容易发现两数的lowbit就是它们岔道结点的深度,所以先建树后对于一个数字依次把每次分岔开的另一边的size乘上权值累加答案。

法二:从高位到低位分组求和,即第一位1在上,0在下,则两边之间互相计算过后就再无影响,只剩下各自内部的事情再处理。由于排序后数据的有序性使分治可行。

法三:排序后对于一个数字,它和后面的数字的lowbit有单调性……然后可以维护它,相当麻烦,不再赘述。

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=50010,MOD=998244353;

int size[maxn*50],t[maxn*50][2],tot,a[maxn],n;
void insert(int x,int dep,int num)
{
    if(dep>30)return;
    if(t[x][num&1])
    {
        size[t[x][num&1]]++;
    }
    else
    {
        t[x][num&1]=++tot;
        t[t[x][num&1]][0]=t[t[x][num&1]][1]=0;
        size[t[x][num&1]]=1;
    }
    insert(t[x][num&1],dep+1,num>>1);
}
int query(int x,int dep,int num)
{
    if(dep>30)return 0;
    long long ansnow=((t[x][(num&1)^1]?size[t[x][(num&1)^1]]:0)<<dep)%MOD;
    if(t[x][(num&1)])ansnow=((ansnow+query(t[x][num&1],dep+1,num>>1)))%MOD;
    return (int)(ansnow%MOD);
}
int main()
{
    int T,now=0;
    scanf("%d",&T);
    long long ans=0;
    while(T--)
    {
        now++;
        tot=1;
        t[1][0]=t[1][1]=0;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            insert(1,0,a[i]);
        }
        ans=0;
        for(int i=1;i<=n;i++)ans=(ans+query(1,0,a[i]))%MOD;
        printf("Case #%d: %d\n",now,(int)(ans%MOD));
    }
    return 0;
}

时间: 2024-08-04 07:58:53

【HDU】5269 ZYB loves Xor I的相关文章

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( 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树.然后遍历的时候如果同时 有左右孩子的话那

【HDU】2147 kiki&#39;s game

http://acm.hdu.edu.cn/showproblem.php?pid=2147 题意:n×m的棋盘,每次可以向左走.向下走.向左下走,初始在(1, m),n,m<=2000,问先手是否胜利. #include <cstdio> using namespace std; int main() { int n, m; while(scanf("%d%d", &n, &m), n|m) (n&1)&&(m&1)?

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】4923 Room and Moor(2014多校第六场1003)

Room and Moor Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 263    Accepted Submission(s): 73 Problem Description PM Room defines a sequence A = {A1, A2,..., AN}, each of which is either 0

【HDU】4888 Redraw Beautiful Drawings 网络流【推断解是否唯一】

传送门:pid=4888">[HDU]4888 Redraw Beautiful Drawings 题目分析: 比赛的时候看出是个网络流,可是没有敲出来.各种反面样例推倒自己(究其原因是不愿意写暴力推断的).. 首先是简单的行列建边.源点向行建边.容量为该行元素和,汇点和列建边.容量为该列元素和.全部的行向全部的列建边,容量为K. 跑一次最大流.满流则有解,否则无解. 接下来是推断解是否唯一. 这个题解压根没看懂.还是暴力大法好. 最简单的思想就是枚举在一个矩形的四个端点.设A.D为主对角

【HDU】4918 Query on the subtree 点分治+树状数组

传送门:[HDU]4918 Query on the subtree 题目分析: 首先,简化问题. 1.求一次到点u的距离不超过d的点的个数.很容易,一次O(NlogN)的点分治便可以完成. 2.多次进行操作1.此时不能每次都O(NlogN)了,太慢了.我们考虑到对于点分治,树的重心一共有logN层,第一层为整棵树的重心,第二层为第一层重心的子树的重心,以此类推,每次至少分成两个大小差不多的子树,所以一共有logN层.而且,对于一个点,他最多只属于logN个子树,也就是最多只属于logN个重心.