版权声明:作为一个蒟蒻,转载时请通知我这个蒟蒻 https://blog.csdn.net/zyszlb2003/article/details/89838738
欢迎大家访问我的老师的OJ———caioj.cn
题面描述
思路
数学期望
首先,位运算不会进位,各位之间互不影响。
那么我们可以尝试把 个自然数都分成 位,对每一位分别进行处理。设 是一个 序列, 等于 的第 位。
设 为数字 上一次出现的位置。
按照题目中所描述的,我们可以分类讨论当 ,与 的情况。
时,
也就是不进行任何操作,但也要算期望。
注:下列 操作是因为未进行交换操作之前的 是不同的取法。
时,当 , ,若 , ,即
扫描二维码关注公众号,回复:
6163436 查看本文章
当 ,
计算· 略麻烦。
我们需要多开两个变量 来记录可以满足 和为 或 的总长度。
当 时,
否则,
当 时,
AC code
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#define gc getchar()
using namespace std;
const int N=1e5+10;
inline void qr(int &x)
{
x=0;int f=1;char c=gc;
while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc;}
while(c>='0'&&c<='9'){x=x*10+(c^48);c=gc;}
x*=f;
}
int n,a[N],b[N];
double ansxor=0,ansor=0,ansand=0;
inline void rainbow(int k)
{
int last[2]={0,0},c1=0,c2=0;
double w=(double)(1<<k)/n/n;
for(int i=1;i<=n;i++)
{
b[i]=(a[i]>>k)&1;
if(b[i])
{
ansxor+=w;
ansand+=w;
ansor+=w;
}
if(!b[i])ansor+=w*last[1]*2;//1~last[1]
else
{
ansand+=w*(i-1-last[0])*2;//last[0]+1~r-1
ansor+=w*(i-1)*2;//1~r-1
}
ansxor+=w*(b[i]?c1:c2)*2;
c1++;
if(b[i])swap(c1,c2);
last[b[i]]=i;
}
}
int main()
{
qr(n);
for(int i=1;i<=n;i++)qr(a[i]);
for(int i=0;i<31;i++)rainbow(i);
printf("%.3lf %.3lf %.3lf\n",ansxor,ansand,ansor);
return 0;
}