Gym102331B Bitwise Xor

Bitwise Xor

Zhong Ziqian got an integer array (a_1, a_2, ldots, a_n) and an integer (x) as birthday presents.

Every day after that, he tried to find a non-empty subsequence of this array (1 leq b_1 < b_2 < ldots < b_k leq n), such that for all pairs ((i, j)) where (1 leq i < j leq k), the inequality (a_{b_i} oplus a_{b_j} geq x) held. Here, (oplus) is the bitwise exclusive-or operation.

Of course, every day he must find a different subsequence.

How many days can he do this without repeating himself? As this number may be very large, output it modulo (998\,244\,353).

(1 leq n leq 300\,000, 0 leq x leq 2^{60}-1)

题解

https://drive.google.com/file/d/1BuDTosfabqMZGEu2zyqTmkS2QsIYWsG6/view

若干个数两两异或的最小值必在排序后相邻两个取到。排序后直接用Trie优化DP即可。

具体而言,用f[i]表示以第i个数结尾的子序列个数。在Trie中查询更新,然后把它插入到Trie中。

时间复杂度 (O(n log x))

CO int N=3e5+10;
int64 a[N];
int ch[N*61][2],sum[N*61],tot=1;

void insert(int x,int64 p,int d,int v){
	sum[x]=add(sum[x],v);
	if(d==-1) return;
	int c=p>>d&1;
	if(!ch[x][c]) ch[x][c]=++tot;
	insert(ch[x][c],p,d-1,v);
}
int query(int x,int64 l,int64 r,int d){
	if(!x) return 0;
	if(d==-1) return sum[x];
	if(r>>d&1){
		if(l>>d&1) return query(ch[x][0],l,r,d-1);
		else return query(ch[x][1],l,r,d-1);
	}
	else{
		if(l>>d&1) return add(sum[ch[x][0]],query(ch[x][1],l,r,d-1));
		else return add(query(ch[x][0],l,r,d-1),sum[ch[x][1]]);
	}
}
int main(){
	int n=read<int>();
	int64 X=read<int64>();
	for(int i=1;i<=n;++i) read(a[i]);
	sort(a+1,a+n+1);
	int ans=0;
	for(int i=1;i<=n;++i){
		int f=add(1,query(1,a[i],X,60));
		ans=add(ans,f);
		insert(1,a[i],60,f);
	}
	printf("%d
",ans);
	return 0;
}
原文地址:https://www.cnblogs.com/autoint/p/12468236.html