【Description】
琪露诺是一个可爱的小女孩,经常会思考诸如“到底⑨是 baka,还是 baka 是⑨”之类的
问题。有天,慧音老师给琪露诺出了一道题目:
给定一个长度为N的自然数数列,等概率地随机选取一对l,r。如果l>r,就交换l,r。
求子序列A[l..r]的xor和,and和,or和的期望
A[l..r]的xor和的定义是:A[l] xor A[l + 1] xor .. xor A[r]。
and和、or 和的定义类似。
关于xor,and,or,期望的详细信息见附件。
【Input】
第一行一个正整数N,代表数列长度。
第二行N个自然数描述数列A
【Output】
一行三个实数,分别表示xor和、and和、or和的期望(注意顺序)。
【Sample Input1】
2
4 5
【Sample Output1】
2.750 4.250 4.750
【Sample Input2】
3
1 0 1
【Sample Output2】
0.667 0.222 0.889
对于20%数据,1<=N<=100
对于40%数据,1<=N<=1000
对于另外30%数据,A中只包含0和1
对于100%数据,1<=N<=100000,0 <= A中所有数 <= 10^9
有关于位运算的一点科普:
关于三种逻辑运算的规则 a and b = true 当且仅当 a 和 b 都是 true a or b = true 当且仅当 a 和 b 中有一个是 true a xor b = true 当且仅当 a 和 b 不相等
and 运算本来是一个逻辑运算符,但整数与整数之间也可以进行 and 运算。举个例子,6 的二进制是 110, 11 的二进制是 1011,那么 6 and 11 的结果就是 2,它是二进制对应位进行逻辑运算的结果(0 表示 false,1 表示 true,空位都当 0 处理): 110 and 1011 ---------- 0010 --> 2
有关于期望的一点科普:
数学期望是随机变量最基本的数字特征之一。它反映随机变量平均取值的大小,又称期望或均值。它是简 单算术平均的一种推广。例如某城市有 10 万个家庭,没有孩子的家庭有 1000 个,有一个孩子的家庭有 9 万个,有两个孩子的家庭有 6000 个,有 3 个孩子的家庭有 3000 个,则该城市中任一个家庭中孩子的数目 是一个随机变量,它可取值 0,1,2,3,其中取 0 的概率为 0.01,取 1 的概率为 0.9,取 2 的概率为 0.06, 取 3 的概率为 0.03,它的数学期望为 0×0.01+1×0.9+2×0.06+3×0.03 等于 1.11,即此城市一个家庭平 均有小孩 1.11 个
对于40的数据,暴力写得丑也能过
有0,1的情况就有搞头了
经过数学归纳‘
可以得到如下规律
对于1——i
and的结果!之前的连续1的数量
or结果i – 之前的连续0的数量
xor结果1的数量为奇数的数量
然后进行计算就好了
对于更刁钻的数据
可以干他
所有的数据二进制下都不超过32位,而每一位时互不影响的
所以对于每一个位都算一次,最后求和
由于每个现象都是等概率的
琪露诺是一个可爱的小女孩,经常会思考诸如“到底⑨是 baka,还是 baka 是⑨”之类的
问题。有天,慧音老师给琪露诺出了一道题目:
给定一个长度为N的自然数数列,等概率地随机选取一对l,r。如果l>r,就交换l,r。
求子序列A[l..r]的xor和,and和,or和的期望
A[l..r]的xor和的定义是:A[l] xor A[l + 1] xor .. xor A[r]。
and和、or 和的定义类似。
关于xor,and,or,期望的详细信息见附件。
【Input】
第一行一个正整数N,代表数列长度。
第二行N个自然数描述数列A
【Output】
一行三个实数,分别表示xor和、and和、or和的期望(注意顺序)。
【Sample Input1】
2
4 5
【Sample Output1】
2.750 4.250 4.750
【Sample Input2】
3
1 0 1
【Sample Output2】
0.667 0.222 0.889
对于20%数据,1<=N<=100
对于40%数据,1<=N<=1000
对于另外30%数据,A中只包含0和1
对于100%数据,1<=N<=100000,0 <= A中所有数 <= 10^9
有关于位运算的一点科普:
关于三种逻辑运算的规则 a and b = true 当且仅当 a 和 b 都是 true a or b = true 当且仅当 a 和 b 中有一个是 true a xor b = true 当且仅当 a 和 b 不相等
and 运算本来是一个逻辑运算符,但整数与整数之间也可以进行 and 运算。举个例子,6 的二进制是 110, 11 的二进制是 1011,那么 6 and 11 的结果就是 2,它是二进制对应位进行逻辑运算的结果(0 表示 false,1 表示 true,空位都当 0 处理): 110 and 1011 ---------- 0010 --> 2
有关于期望的一点科普:
数学期望是随机变量最基本的数字特征之一。它反映随机变量平均取值的大小,又称期望或均值。它是简 单算术平均的一种推广。例如某城市有 10 万个家庭,没有孩子的家庭有 1000 个,有一个孩子的家庭有 9 万个,有两个孩子的家庭有 6000 个,有 3 个孩子的家庭有 3000 个,则该城市中任一个家庭中孩子的数目 是一个随机变量,它可取值 0,1,2,3,其中取 0 的概率为 0.01,取 1 的概率为 0.9,取 2 的概率为 0.06, 取 3 的概率为 0.03,它的数学期望为 0×0.01+1×0.9+2×0.06+3×0.03 等于 1.11,即此城市一个家庭平 均有小孩 1.11 个
对于40的数据,暴力写得丑也能过
有0,1的情况就有搞头了
经过数学归纳‘
可以得到如下规律
对于1——i
and的结果!之前的连续1的数量
or结果i – 之前的连续0的数量
xor结果1的数量为奇数的数量
然后进行计算就好了
对于更刁钻的数据
可以干他
所有的数据二进制下都不超过32位,而每一位时互不影响的
所以对于每一个位都算一次,最后求和
由于每个现象都是等概率的
所以直接算平均数,期望就是吓唬你的
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<map>
using namespace std;
map<string,bool> da_shen_bao_you;
const int maxn=100005;
int a[maxn],b[maxn];
int n;
double ans_or,ans_xor,ans_and;
void calc(int w)
{
for(int i=1;i<=n;i++)
b[i]=(a[i]&(1<<w));
//取位 单独处理一下这些值
//然后开始处理这个基佬数列
//只有0,1的数列,额这不能叫基佬
// LJT ZAI TAYZ BRDL
int pos[2]={0,0},amout[2]={0,0};
for(int i=1;i<=n;i++)
{
if(i!=1)
{
//第一个数就别玩了
ans_xor+=(double)(1<<w)/n/n*amout[!b[i]];
//亦或
if(b[i])
{
ans_and+=(double)(1<<w)/n/n*(i-1-pos[0]);
ans_or+=(double)(1<<w)/n/n*(i-1);
}
else
{
//0就别玩and了
ans_and+=(double)(1<<w)/n/n*(pos[1]);
}
}
pos[b[i]]=i;
//记录最后的0/1的位置
if(!b[i])
amout[0]++;
else
{
swap(amout[0],amout[1]);
amout[1]++;
}
//用来算xor的值
}
for (int i = 1; i <= n; i++)
if (b[i])
{
ans_or+=(double)(1<<w)/n/n/2;
ans_xor+=(double)(1<<w)/n/n/2;
ans_and+=(double)(1<<w)/n/n/2;
}
//不要忘了自己啊
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=0;i<31;i++)
{
calc(i);
}
printf("%.3lf %.3lf %.3lf\n",ans_xor*2,ans_and*2,ans_or*2);
return 0;
}