Description
魔法之龙玛里苟斯最近在为加基森拍卖师的削弱而感到伤心,于是他想了一道数学题。
S
是一个可重集合,
等概率随机取
S
的一个子集
计算出
A
中所有元素异或
Input
第一行两个正整数 n,k 。
以下
n
行每行一个整数,表示
1≤n≤100000,1≤k≤5,ai≥0 。最终答案小于 263 。 k=1,2,3,4,5 各自占用 20% 的数据
Output
如果结果是整数,直接输出。如果结果是小数(显然这个小数是有限的),输出精确值(末尾不加多余的0)。
Sample Input
4 2
0
1
2
3
Sample Output
3.5
Solution
k=1
时,考虑每一位对答案的影响,对于第
i
位,如果这
k≥3
时,由于答案不超过
263
,故线性基维数
m
不会超过
Code
#include<cstdio>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn=100005;
int n,k,base[30];
ll a[maxn];
int main()
{
scanf("%d%d",&n,&k);
if(k==1)
{
ull ans=0,temp;
for(int i=1;i<=n;i++)
{
scanf("%llu",&temp);
ans|=temp;
}
printf("%llu%s\n",ans>>1,ans&1?".5\n":"\n");
}
else if(k==2)
{
ll s=0;
for(int i=1;i<=n;i++)scanf("%lld",&a[i]),s|=a[i];
ll ans=0;
int res=0;
for(int i=0;i<32;i++)
for(int j=0;j<32;j++)
{
if(!(s>>i&1)||!(s>>j&1))continue;
int f=0;
//f表示是否存在(0,1)或者(1,0)
for(int k=1;k<=n;k++)
if((a[k]>>i&1)!=(a[k]>>j&1))
{
f=1;
break;
}
if(i+j-1-f<0)res++;
else ans+=(1ll<<(i+j-1-f));
}
ans+=res>>1;
printf("%lld%s",ans,res&1?".5\n":"\n");
}
else
{
for(int i=1;i<=n;i++)
{
int temp;
scanf("%d",&temp);
for(int j=22;j>=0;j--)
if(temp>>j&1)
{
if(!base[j])
{
base[j]=temp;
break;
}
else temp^=base[j];
}
}
int m=0;
for(int i=0;i<=22;i++)
if(base[i])base[m++]=base[i];
int M=1<<m;
ll ans=0,res=0;
for(int i=1;i<M;i++)
{
int temp=0;
for(int j=0;j<m;j++)
if((i>>j)&1)temp^=base[j];
ll x=0,y=1;
for(int j=0;j<k;j++)
{
x*=temp,y*=temp;
x+=y>>m,y&=(M-1);
}
ans+=x,res+=y;
ans+=res>>m,res&=(M-1);
}
if(res)printf("%lld.5\n",ans);
else printf("%lld\n",ans);
}
return 0;
}