之前做过一道一模一样的题目
连数据范围都一样!!!
但自己还是没能想出那个结论!!!
结论:子序列中两两异或的最小值
>
=
x
>=x
>=x,这个最小值只可能在排序后相邻两项中取得。
也就是说对于
∀
a
≤
b
≤
c
,
m
i
n
(
a
⨁
b
,
b
⨁
c
)
≤
a
⨁
c
\forall a\leq b\leq c,min(a\bigoplus b,b\bigoplus c)\leq a\bigoplus c
∀a≤b≤c,min(a⨁b,b⨁c)≤a⨁c
等于的情况显然。
对于不等于的情况,考虑
a
,
b
,
c
a,b,c
a,b,c不全相等的最高位(二进制),设其值为
A
,
B
,
C
A,B,C
A,B,C
相等的话的
m
i
n
(
a
⨁
b
,
b
⨁
c
)
=
a
⨁
c
=
0
min(a\bigoplus b,b\bigoplus c)= a\bigoplus c=0
min(a⨁b,b⨁c)=a⨁c=0
当
A
⨁
C
=
=
0
A\bigoplus C==0
A⨁C==0时,即
A
=
C
A=C
A=C,有
A
≤
B
≤
C
A\leq B\leq C
A≤B≤C,那么
A
=
B
=
C
A=B=C
A=B=C,违反不全相等前提
因为
A
!
=
C
A!=C
A!=C,则
A
⨁
C
=
=
1
A\bigoplus C==1
A⨁C==1
那么根据抽屉原理,必有
B
=
=
A
∣
∣
B
=
=
C
B==A||B==C
B==A∣∣B==C,即
m
i
n
(
a
⨁
b
,
b
⨁
c
)
=
=
0
min(a\bigoplus b,b\bigoplus c)==0
min(a⨁b,b⨁c)==0
结论得证
有了这个结论这题不就成trie裸题了?
设
f
[
i
]
f[i]
f[i]为做到第
i
i
i个数的答案
则
f
[
i
]
=
1
+
∑
j
=
1
i
−
1
,
(
a
[
j
]
⨁
a
[
i
]
≥
x
)
f
[
j
]
{f[i]=1+\sum_{j=1}^{i-1,(a[j]\bigoplus a[i]\geq x)}f[j]}
f[i]=1+j=1∑i−1,(a[j]⨁a[i]≥x)f[j]
特判
x
=
0
x=0
x=0的情况
#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
#define mo 998244353
using namespace std;
ll i,j,k,m,n,o,p,l,s,t,lim,len,num;
ll trie[25000005][2],a[300005],sum[25000005],f[300005],bas[15000005];
void insert(ll t,ll pos,ll g,ll ad)
{
sum[t]=0;
if (pos==0) {
bas[t]+=ad,bas[t]%=mo;sum[t]=bas[t];return;
}
ll h=g&(1ll<<(pos-1));
if (!h)
{
if (!trie[t][0]) trie[t][0]=++len;
insert(trie[t][0],pos-1,g,ad);
} else {
if (!trie[t][1]) trie[t][1]=++len;
insert(trie[t][1],pos-1,g,ad);
}
if (trie[t][0]) sum[t]+=sum[trie[t][0]],sum[t]%=mo;
if (trie[t][1]) sum[t]+=sum[trie[t][1]],sum[t]%=mo;
}
ll query(ll t,ll pos,ll g)
{
if (pos==0) return 0;
ll h=g&(1ll<<(pos-1)),H=lim&(1ll<<(pos-1));
if (!H)
{
ll s=0;
if (!h)
{
if (trie[t][0]) s+=query(trie[t][0],pos-1,g),s%=mo;
if (trie[t][1]) s+=sum[trie[t][1]],s%=mo;
} else {
if (trie[t][0]) s+=sum[trie[t][0]],s%=mo;
if (trie[t][1]) s+=query(trie[t][1],pos-1,g),s%=mo;
}
return s;
} else {
ll s=0;
if (!h)
{
if (trie[t][1]) s+=query(trie[t][1],pos-1,g),s%=998244353;
} else {
if (trie[t][0]) s+=query(trie[t][0],pos-1,g),s%=998244353;
}
return s;
}
}
void read(ll &x)
{
char ch=getchar();x=0;
while (ch<'0'||ch>'9') ch=getchar();
while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-48,ch=getchar();
}
ll ksm(ll x,ll y)
{
ll ans=1;
for (;y;y>>=1,x=x*x%mo)
if (y&1) ans=ans*x%mo;
return ans;
}
int main()
{
freopen("inception.in","r",stdin);
freopen("inception.out","w",stdout);
read(num),read(n),read(lim);
if (lim==0)
{
printf("%lld\n",ksm(2,n)-1);
return 0;
}
if (lim) lim--;
for (i=1;i<=n;i++) read(a[i]);
sort(a+1,a+n+1),len=1;
for (i=1;i<=n;i++)
f[i]=query(1,60,a[i])+1,
insert(1,60,a[i],f[i]);
ll ans=0;
for (i=1;i<=n;i++) ans=(ans+f[i])%998244353;
printf("%lld\n",ans);
return 0;
}