Solution
分类讨论。
k
=
1
k=1
k=1,可以考虑每位的贡献。若一个位不全为
0
0
0,那么所有的异或和中,有一半这一位为
0
0
0,有一半为
1
1
1,直接算即可。
k
=
2
k=2
k=2,可以考虑把一位的贡献和两位一起产生的贡献分开来算,
(
a
+
b
)
2
=
a
2
+
2
a
b
+
b
2
(a+b)^2=a^2+2ab+b^2
(a+b)2=a2+2ab+b2,一位的贡献很好考虑,直接平方;两位的贡献只有两位都至少有一个
1
1
1才会产生,若
n
n
n个数的两位完全相同,则类比
k
=
1
k=1
k=1的情况,
1
2
1\over 2
21为
1
1
1;否则就是
1
4
1\over4
41为
1
1
1。
k
≥
3
k\ge3
k≥3,设最大的数为
x
x
x,且
2
k
≤
x
<
2
k
2^k \le x<2^k
2k≤x<2k,这些数构成的线性基有
c
n
t
cnt
cnt个元素,那么会有
2
c
n
t
2^{cnt}
2cnt种异或和,其中有一半,即
2
c
n
t
−
1
2^{cnt-1}
2cnt−1种是
≥
2
k
\ge2^k
≥2k的,又因为
∑
x
k
2
c
n
t
≤
2
63
{\sum x^k\over2^{cnt}}\le2^{63}
2cnt∑xk≤263,所以
k
k
k最大只有
22
22
22,完全可以暴力求解。
Code
#include<bits/stdc++.h>
using namespace std;
#define LL unsigned long long
#define pa pair<int,int>
const int Maxn=100010;
const int inf=2147483647;
LL read()
{
LL x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
return x*f;
}
LL a[Maxn],b[65],c[65];int n,k,cnt=0;
LL Ans=0,r=0,o;
void dfs(int x,LL v)
{
if(x>22)
{
if(k==3)r+=v*v*v;
if(k==4)
{
Ans+=(v*v/o)*v*v;
Ans+=(v*v%o*v*v/o);
r=(r+v*v%o*v%o*v%o);
}
if(k==5)
{
Ans+=(v*v*v/o)*v*v;
Ans+=(v*v*v%o*v*v/o);
r=(r+v*v%o*v%o*v%o*v%o);
}
Ans+=r/o;r%=o;
return;
}
if(!c[x]){dfs(x+1,v);return;}
dfs(x+1,v);
dfs(x+1,v^c[x]);
}
int main()
{
n=read(),k=read();
for(int i=1;i<=n;i++)a[i]=read();
LL ans=0;
for(int i=63;i>=0;i--)
{
b[i]=0;
for(int j=1;j<=n;j++)
if((1LL<<i)&a[j]){b[i]=1;break;}
}
if(k==1)
{
for(int i=0;i<=63;i++)if(b[i])ans+=(1LL<<i);
if(ans&1)printf("%llu.5",ans/2LL);
else printf("%llu",ans/2LL);
}
else if(k==2)
{
for(int i=0;i<=63;i++)
if(b[i])
{
for(int j=i+1;j<=63;j++)
if(b[j])
{
bool flag=true;
for(int l=1;l<=n;l++)
if(((a[l]>>i)&1)!=((a[l]>>j)&1)){flag=false;break;}
if(flag)ans+=(1LL<<(i+j+1));
else ans+=(1LL<<(i+j));
}
}
for(int i=0;i<=63;i++)if(b[i])ans+=(1LL<<(i*2));
if(ans&1)printf("%llu.5",ans/2LL);
else printf("%llu",ans/2LL);
}
else
{
for(int i=1;i<=n;i++)
{
LL x=a[i];
for(int j=63;j>=0;j--)
if((1LL<<j)&x)
{
if(!c[j]){c[j]=x;cnt++;break;}
x^=c[j];
}
}
o=(1LL<<cnt);
dfs(0,0);
printf("%llu",Ans);
if(r)puts(".5");
}
}