1 条题解
-
0
自动搬运
来自洛谷,原作者为

Elaina_0
今朝依旧,今后亦然。搬运于
2025-08-24 22:58:36,当前版本为作者最后更新于2024-05-24 17:01:11,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
P10500 Rainbow的信号
谢谢管理大大的审核,
顺便无耻的推一下 blog。
思路
因为位运算当前位的结果只与当前位有关,所以可以单独考虑每一位,最后将每一位的贡献相加就是答案。
由于 , 是等概率选取,所以选取长度为 的区间()的概率是 ,选取其他区间()的概率是 。
设 表示第 个数字的第 个二进制位的值; 表示 最后出现的位置。
分别讨论三种运算的期望:
-
的期望
-
若第 个数字的第 位是 ,以 为右端点,在 区间内任取两个数组成的区间 和都是 ,因此她的贡献为:
$$\begin{cases} last[0] = x 2^k \times \frac{1}{n^2}\\ last[0]+1 \neq x 2^k \times (x-(last[0]+1)) \times \frac{2}{n^2} \end{cases}$$ -
若第 个数字的第 为是 ,不存在左端点与 的组合使得区间的 和为 。
-
-
的期望
-
若第 个数字的第 位是 ,前面所有点都可以与 组成区间使得 和为 ,所以她的贡献为:
$$\begin{cases} l = x 2^k \times \frac{1}{n^2}\\ l \neq x 2^k \times (x−1) \times \frac{2}{n^2} \end{cases}$$- 若第 个数字的第 位是 ,以 为右端点, 的数字可以选作左端点,所以她的贡献为:
-
-
的期望
设 是 区间的 和, 表示 区间 和为 的 个数, 表示 区间 和为 的 个数。
从 开始,将 向左移动,若第 位是 则 取反,否则 不变。
-
若第 个数字的第 位是 ,则 只能选择 表示的部分,所以她的贡献为:
-
若第 个数字的第 位是 ,则 只能选择 表示的部分,所以她的贡献为:
最后还要加上 的贡献:
当右端点 增加 ,令 增加 。
若 ,则还需交换 。
-
CODE
#include<bits/stdc++.h> using namespace std; #define int long long #define Elaina 0 const int N=100010; inline int read(){ int x=0,f=1; char ch=getchar(); for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1; for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0'; return x*f; } int n,a[N]; int last[3],c1,c2; double ansand,ansor,ansxor; main(){ n=read(); for(int i=1;i<=n;i++) a[i]=read(); for(int i=0;i<=30;i++){ last[0]=last[1]=0; c1=c2=0; for(int j=1;j<=n;j++){ int now=(a[j]>>i)&1; double ret=(double)(1<<i)/(n*n); if(now){ ansand+=ret+2.0*ret*(j-(last[0]+1)); ansor+=ret+2.0*ret*(j-1); ansxor+=ret+2.0*ret*c1; }else{ ansor+=2.0*ret*last[1]; ansxor+=2.0*ret*c2; } last[now]=j; c1++; if(now) swap(c1,c2); } } printf("%.3lf %.3lf %.3lf",ansxor,ansand,ansor); return Elaina; } -
- 1
信息
- ID
- 10178
- 时间
- 1000ms
- 内存
- 512MiB
- 难度
- 4
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者