ZYB loves Xor I HDU - 5269(01字典树,二进制,异或,lowbit)

题目链接

题意:给出一列数,求任意两个数的异或值得lowbit值和。PS:一个数的lowbit为,第一个不为0的数前有k个0,则为2^k。

题解:利用字典树存储这些数的二进制,每次插入将相应的异或的lowbit加入ans里面(其实就是简单的排列组合)

AC代码:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn=2e6+5;
const ll mod = 998244353;
ll son[maxn][3],sum[maxn],idx;
ll bit[35],ans;
void init(){
	memset(son,-1,sizeof(son));
	memset(sum,0,sizeof(sum));
	idx=0,ans=0;
}
void insert(ll x){
	int root=0;
	for(int i=0;i<=30;i++){
		int v=x&(1<<i)?1:0;//获取x的二进制第i位,这里必须这样判断,得到0说明这一位是0,否者大于零就是1 
		if(son[root][v]==-1)son[root][v]=++idx;//不存在就创建结点 
		if(son[root][1^v]!=-1)//存在这一位与v相异的数  
		ans=(ans+bit[i]*sum[son[root][1^v]]%mod)%mod;
		root=son[root][v];
		sum[root]+=1;//当前结点分叉+1 
	}
}
int main(){
	int t,kase=1,n;
	cin>>t;
	bit[0]=1;
	for(int i=1;i<=30;i++)bit[i]=bit[i-1]*2;
	while(t--){
		cin>>n;
		init();
		for(int i=1;i<=n;i++){
			ll x;
			cin>>x;
			insert(x);
		}
		ans=(ans*2)%mod;
		printf("Case #%d: %lld\n",kase++,ans); 
	}
}

猜你喜欢

转载自blog.csdn.net/Alanrookie/article/details/107342278