Rainbow的信号[CH3801]

版权声明:作为一个蒟蒻,转载时请通知我这个蒟蒻 https://blog.csdn.net/zyszlb2003/article/details/89838738

欢迎大家访问我的老师的OJ———caioj.cn

题面描述

传送门

思路

数学期望 E ( x ) = P ( x ) v a l ( x ) E(x)=P(x)*val(x)

首先,位运算不会进位,各位之间互不影响。

那么我们可以尝试把 N N 个自然数都分成 31 31 位,对每一位分别进行处理。设 B B 是一个 01 01 序列, B i B_i 等于 A i A_i 的第 k k 位。

w = 2 k N 2 , l a s t k \large w=\frac{2^{k}}{N^2},last_k 为数字 k [ 0 , 1 ] k\in[0,1] 上一次出现的位置。

按照题目中所描述的,我们可以分类讨论当 l = r l=r ,与 l < r l<r 的情况。

l = r l=r 时, a n s x o r + = w , a n s o r + = w , a n s a n d + = w ansxor+=w,ansor+=w,ansand+=w

也就是不进行任何操作,但也要算期望。

注:下列 2 *2 操作是因为未进行交换操作之前的 ( l , r ) , ( r , l ) (l,r),(r,l) 是不同的取法。

l < r l<r 时,当 B r = 1 , l [ 1 , r 1 ] B_r=1,l\in[1,r-1] a n s o r + = w ( r 1 ) 2 ansor+=w*(r-1)*2 ,若 B r = 0 B_r=0 a n s o r + = w l a s t 1 2 ansor+=w*last_1*2 ,即 l [ 1 , l a s t 1 ] l\in[1,last_1]

扫描二维码关注公众号,回复: 6163436 查看本文章

B r = 1 , l [ l a s t 0 + 1 , r 1 ] B_r=1,l\in[last_0+1,r-1] a n s a n d + = w ( r 1 l a s t 0 1 + 1 ) 2 ansand+=w*(r-1-last_0-1+1)*2

计算· a n s x o r ansxor 略麻烦。

我们需要多开两个变量 c 1 , c 2 c_1,c_2 来记录可以满足 [ l , r 1 ] xor [l,r-1]\operatorname{xor} 和为 0 0 1 1 的总长度。

B r = 1 B_r=1 时, a n s x o r = w 2 c 1 ansxor=w*2*c_1

否则, a n s x o r = w 2 c 2 ansxor=w*2*c_2

B r = 1 B_r=1 时, swap ( c 1 , c 2 ) \operatorname{swap}(c1,c2)

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

猜你喜欢

转载自blog.csdn.net/zyszlb2003/article/details/89838738