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;
}