题目
分析
首先位运算没有进位,这样可以让它一位一位进行,如题所述,设
x
x
x表示
a
i
a_i
ai的第
k
k
k位,当
l
=
=
r
l==r
l==r的时候概率为
1
n
2
\frac{1}{n^2}
n21,然后当
x
=
=
1
x==1
x==1时数学期望为
2
k
n
2
\frac{2^k}{n^2}
n22k。
Then,当
l
<
r
l<r
l<r时,概率为
2
n
2
\frac{2}{n^2}
n22,对于
a
n
d
and
and,找到前面最后一个0的位置
t
t
t,那么可选的
l
l
l的个数,为
r
−
t
−
1
r-t-1
r−t−1。
对于
o
r
or
or,当
x
x
x为1,时为任何数,否则个数为最后一个1的位置
对于
x
o
r
xor
xor,当
x
x
x为1时就会改变个数,所以说每遇到
1
1
1的时候个数肯定是会交换的,具体就不多解释
代码
#include <cstdio>
#include <cctype>
#define rr register
using namespace std;
int n,a[100001]; double sxor,sand,suor;
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans;
}
inline void answ(int k){
rr int p0=0,p1=0,c1=0,c2=0;
for (rr int i=1;i<=n;++i)
if ((a[i]>>k)&1){
sxor+=(1<<k)*1.0/n/n;
sand+=(1<<k)*1.0/n/n;
suor+=(1<<k)*1.0/n/n;
sand+=(1<<k)*2.0/n/n*(i-1-p0);
suor+=(1<<k)*2.0/n/n*(i-1);
sxor+=(1<<k)*2.0/n/n*c1;
++c1; c1^=c2,c2^=c1,c1^=c2; p1=i;
}
else{
suor+=(1<<k)*2.0/n/n*p1;
sxor+=(1<<k)*2.0/n/n*c2;
++c1; p0=i;
}
}
signed main(){
n=iut();
for (rr int i=1;i<=n;++i) a[i]=iut();
for (rr int i=0;i<30;++i) answ(i);
printf("%.3lf %.3lf %.3lf",sxor,sand,suor);
return 0;
}