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\n",ans);
	return 0;
}

posted on 2020-03-12 12:00  autoint  阅读(339)  评论(0编辑  收藏  举报

导航