TYZ 09/08 琪露诺的算术教室

【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】 

4 5 
【Sample Output1】 
2.750 4.250 4.750 
【Sample Input2】 

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;
 } 







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值