HDU 5269这题有点难受,看了好多张博客都是用指针写的,无奈不会指针,所以我查找了很多博客,终于找到几篇用数组写的
之前的xor sum 是从最高位开始找,现在的 ZYB loves Xor I 是从最低位开始找,求第几个不同,呢么这个就是最低位,题目中的lowbit(x)=(y^x)取的最低位
2^k
,则可以用字典树,把每个数的二进制插入前缀树上,然后判断每一位,然后判断该位是否与其他位有不同,如果不同把当前的2^i
加上和即可
传送门:01字典树+逆推
AC代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
//01字典树
#define ll long long
const ll maxn=30*50005;
ll tire[maxn][2];
ll num[maxn];//这么多个节点
long long Pow[30],tot,ans,n;
const ll mod=998244353;
void init()
{
Pow[0]=1;
for(ll i=1; i<=30; i++)
{
Pow[i]=2*Pow[i-1];
}
}
ll insert_num(ll x)
{
ll root=0;
for(ll i=0; i<30; i++)
{
ll id=x>>i&1?1:0;//判断每一位的存在性,1代表存在,0代表不存在
if(tire[root][id^1])
{
//id^c=1说明id和c不同,则反推1^id=c,不同是否存在
ans+=Pow[i]*num[tire[root][id^1]]%mod;
}
if(!tire[root][id])
{
tire[root][id]=++tot;
}
root=tire[root][id];
num[root]++;
}
}
ll a[maxn];
int main()
{
//ll n;
init();
int t,d=0;
scanf("%d",&t);
while(t--)
{
memset(num,0,sizeof(num));
memset(tire,0,sizeof(tire));
scanf("%lld",&n);
ans=0;
tot=0;
for(ll i=0; i<n; i++)
{
scanf("%lld",&a[i]);
insert_num(a[i]);
}
printf("Case #%d: %lld\n",++d,ans*2%mod);
}
}