给定一个长度为 n n n 的非负整数列 a 1 , a 2 , … , a n a_1, a_2, \dots , a_n a1,a2,…,an 和非负整数 x x x, 求有多少个非空子序列 1 ≤ b 1 < b 2 < ⋅ ⋅ ⋅ < b k ≤ n 1 \leq b_1 < b_2 < · · · < b_k \leq n 1≤b1<b2<⋅⋅⋅<bk≤n,满足对任意的 ( i , j ) ( 1 ≤ i < j ≤ k ) (i, j)(1 \leq i < j \leq k) (i,j)(1≤i<j≤k) 都有 a b i ⊕ a b j ≥ x a_{b_i} \oplus a_{b_j} \ge x abi⊕abj≥x。其中 ⊕ \oplus ⊕ 表示按位异或。
由于这个数可能非常大,你只需要回答这个数除以 998244353 998244353 998244353 的余数即可。
第一行两个整数 n , x n, x n,x。
第二行 n n n 个整数 a 1 , a 2 , . . . , a n a1, a2, . . . , an a1,a2,...,an。
一行一个整数,表示满足条件的子序列的个数除以 998244353 998244353 998244353 的余数。
样例输入 1
3 0
0 1 2
样例输出 1
7
样例输入 2
3 2
0 1 2
样例输出 2
5
样例输入 3
3 3
0 1 2
样例输出 3
4
样例输入 4
7 4
11 5 5 8 3 1 3
样例输出 4
35
样例解释
第一组样例数据中,所有 2 3 − 1 2^3 − 1 23−1 个非空子序列都合法。
第二组样例数据中,除 [ 1 , 2 ] [1, 2] [1,2] 和 [ 1 , 2 , 3 ] [1, 2, 3] [1,2,3] 外,所有非空子序列都合法。
第三组样例数据中,合法的子序列有 [ 1 ] , [ 2 ] , [ 3 ] [1], [2], [3] [1],[2],[3] 和 [ 2 , 3 ] [2, 3] [2,3]。
对于 100 % 100\% 100% 的测试点,满足 1 ≤ n ≤ 3 × 1 0 5 , 0 ≤ x , a i < 2 60 1 \leq n \leq 3 \times 10^5, 0 \leq x,a_i < 2^{60} 1≤n≤3×105,0≤x,ai<260。
对于 10 % 10\% 10% 的测试点,满足 n ≤ 20 n \leq 20 n≤20。
对于另外 20 % 20\% 20% 的测试点,满足 n ≤ 5000 n \leq 5000 n≤5000。
对于另外 50 % 50\% 50% 的测试点,满足 n ≤ 1 0 5 n \leq 10^5 n≤105。
jly csp2020 模拟1
设数组为
a
[
]
a[]
a[],按最高位升序排序,设
x
x
x最高位为
t
o
p
x
top_x
topx
对于两个数
a
[
i
]
,
a
[
j
]
a[i],a[j]
a[i],a[j]
若
t
o
p
i
<
t
o
p
x
,
t
o
p
j
<
t
o
p
x
top_i<top_x,top_j<top_x
topi<topx,topj<topx,则
i
,
j
i,j
i,j不能同时选。
若
t
o
p
i
<
t
o
p
x
,
t
o
p
j
=
=
t
o
p
x
top_i<top_x,top_j==top_x
topi<topx,topj==topx,此时用
t
r
i
e
trie
trie树计算。
若
t
o
p
i
=
=
t
o
p
x
,
t
o
p
j
=
=
t
o
p
x
top_i==top_x,top_j==top_x
topi==topx,topj==topx,则
i
,
j
i,j
i,j不能同时选。
若
t
o
p
i
=
=
t
o
p
j
,
t
o
p
i
>
t
o
p
x
top_i==top_j,top_i>top_x
topi==topj,topi>topx,此时去掉最高位,递归往下判断,最多
l
o
g
log
log层。
其他情况随意选,即乘法原理。
时间复杂度
O
(
n
l
o
g
2
n
)
O(nlog^2n)
O(nlog2n)
但
远
远
达
不
到
\sout{但远远达不到}
但远远达不到
#include<bits/stdc++.h>
#define N 300005
typedef long long ll;
using namespace std;
const int mod=998244353;
inline ll read(){
ll x=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+s-'0';s=getchar();}
return x*f;
}
int tot=1,t[N*59][2],cnt[N*59];
ll fl[N*59],nfl,e[60];
inline void add(ll x){
int now=1;
for(int i=59;i+1;--i){
int c=((x>>i)&1);
if(fl[t[now][c]]!=nfl)t[now][c]=++tot,cnt[tot]=0,fl[tot]=nfl;
cnt[now]++;now=t[now][c];
}
cnt[now]++;
}
inline int get(ll x,ll num){
int ans=0,now=1;
for(int i=59;i+1;--i){
int c=((x>>i)&1),tc=((num>>i)&1);
if(tc==0&&fl[t[now][c^1]]==nfl)ans=(ans+cnt[t[now][c^1]])%mod;
now=t[now][tc^c];if(fl[now]!=nfl)return ans;
}
ans=(ans+cnt[now])%mod;
return ans;
}
ll a[N];
inline int top(ll x){
for(int i=59;i+1;--i){
if((x>>i)&1)return i;
}
return -1;
}
inline int cal(int l,int mid,int r,ll num){
for(int i=1;i<=tot;++i)t[i][0]=t[i][1]=0;
tot=1;fl[tot]=++nfl;cnt[1]=0;
for(int i=l;i<=mid;++i)add(a[i]);
int ans=0;
if(l<=mid){
for(int i=mid+1;i<=r;++i){
ans=(ans+get(a[i],num))%mod;
}
}
return ans+(r-mid);
}
int work(int l,int r,ll num){
sort(a+l,a+r+1);
int ans=1,low=0,mid=0,up=0,ntop=top(num),las=l-1,lto,c=1;
for(int i=l;i<=r;++i){
int to=top(a[i]);
if(to<ntop)low++;
if(to==ntop){
if(mid==0)ans+=low;
mid++;
}
if(to>ntop){
if(up==0)ans=(ans+cal(l,l+low-1,l+low-1+mid,num))%mod,las=i,lto=to;
++up;
if(to!=lto){
for(int j=las;j<i;++j){
a[j]-=e[lto];
}
c=1ll*c*(work(las,i-1,num))%mod;
las=i,lto=to;
}
}
}
if(mid==0)ans+=low;
if(up==0)ans=(ans+cal(l,l+low-1,l+low-1+mid,num))%mod;
if(las!=l-1){
for(int j=las;j<=r;++j){
a[j]-=e[lto];
}
c=1ll*c*(work(las,r,num))%mod;
}
return 1ll*ans*c%mod;
}
inline int power(int x,int c){
int now=1;
while(c){
if(c&1)now=1ll*now*x%mod;
x=1ll*x*x%mod;c>>=1;
}
return now;
}
int main(){
int n=read();ll x=read();
e[0]=1;for(int i=1;i<=59;++i)e[i]=e[i-1]<<1;
for(int i=1;i<=n;++i)a[i]=read();
int ans;
if(x==0)ans=power(2,n)-1;
else ans=work(1,n,x)-1;
printf("%d\n",(ans+mod)%mod);
return 0;
}