题目链接:传送门
题意:
求
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树。然后遍历的时候如果同时
有左右孩子的话那么ans = ans(ans + l_num*r_num)%mod;最后的ans还要乘以2.
代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#define PB push_back
#define MP make_pair
#define REP(i,n) for(int i=0;i<(n);++i)
#define FOR(i,l,h) for(int i=(l);i<=(h);++i)
#define DWN(i,h,l) for(int i=(h);i>=(l);--i)
#define IFOR(i,h,l,v) for(int i=(h);i<=(l);i+=(v))
#define CLR(vis) memset(vis,0,sizeof(vis))
#define MST(vis,pos) memset(vis,pos,sizeof(vis))
#define MAX3(a,b,c) max(a,max(b,c))
#define MAX4(a,b,c,d) max(max(a,b),max(c,d))
#define MIN3(a,b,c) min(a,min(b,c))
#define MIN4(a,b,c,d) min(min(a,b),min(c,d))
#define PI acos(-1.0)
#define INF 1000000000
#define LINF 1000000000000000000LL
#define eps 1e-8
#define LL long long
using namespace std;
const LL mod = 998244353;
const int maxn =5e4+10;
LL a[maxn];
const int max_size = 2;
int id(char c){
return c-'0';
}
struct Trie{
Trie *ch[2];
LL num;
Trie(){
num = 0;
for(int i=0;i<max_size;i++)
ch[i]=NULL;
}
};
void insert_str(Trie *root,char *s){
Trie *p = root;
for(int i=0; p&&s[i] ; i++){
int u = id(s[i]);
if(p->ch[u]==NULL)
p->ch[u] = new Trie;
p=p->ch[u];
p->num++;
//cout<<"***"<<p->num<<endl;
}
}
LL ans;
void dfs(Trie *ff,LL dept){
Trie *p = ff;
if(p->ch[0]!=NULL&&p->ch[1]!=NULL){
ans=(ans+(p->ch[0]->num*p->ch[1]->num)%mod*((1LL<<dept)%mod))%mod;
}
if(p->ch[0]!=NULL)
dfs(p->ch[0],dept+1);
if(p->ch[1]!=NULL)
dfs(p->ch[1],dept+1);
return ;
}
inline LL read()
{
LL x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int main()
{
LL n,t;
int cas=1;
t=read();
char s[50];
while(t--){
Trie *root = new Trie;
n=read();
REP(i,n) a[i]=read();
ans = 0;
REP(i,n){
int cnt = 0;
LL tmp =a[i];
while(tmp){
s[cnt++]=tmp%2+'0';
tmp/=2;
}
FOR(i,cnt,40) s[i]='0';
s[41]=0;
insert_str(root,s);
}
dfs(root,0);
printf("Case #%d: %I64d\n",cas++,(ans<<1)%mod);
}
return 0;
}
HDU 5269 ZYB loves Xor I( 01 Trie 树)
原文:http://blog.csdn.net/bigbigship/article/details/46489383