bzoj-4318 OSU! 【数学期望】
2015-12-13 10:20
381 查看
Description
osu 是一款群众喜闻乐见的休闲软件。我们可以把osu的规则简化与改编成以下的样子:
一共有n次操作,每次操作只有成功与失败之分,成功对应1,失败对应0,n次操作对应为1个长度为n的01串。在这个串中连续的 X个1可以贡献X^3 的分数,这x个1不能被其他连续的1所包含(也就是极长的一串1,具体见样例解释)
现在给出n,以及每个操作的成功率,请你输出期望分数,输出四舍五入后保留1位小数。
Input
第一行有一个正整数n,表示操作个数。接下去n行每行有一个[0,1]之间的实数,表示每个操作的成功率。Output
只有一个实数,表示答案。答案四舍五入后保留1位小数。Sample Input
30.5
0.5
0.5
Sample Output
6.0HINT
【样例说明】000分数为0,001分数为1,010分数为1,100分数为1,101分数为2,110分数为8,011分数为8,111分数为27,总和为48,期望为48/8=6.0
N<=100000
[b]题解[/b]
[b] [/b]大牛都说是水题水题,然而被折磨的欲仙欲死,不过终于在 s_z_l老爷 和 Ngshily大爷 的帮助下搞清楚了,写一写帮助后人吧。。。
1>
首先我们要求的是E(x^3),我们需要明确这里的x^3指的是得分。
我们按照原本的思路,考虑每一位的∆,那么我们假设这一位是1,那么 E((x + 1)^3) = E(x^3) + ∆;
∆ = E((x + 1) ^ 3) - E(x^3) = E((x + 1) ^ 3 - x ^ 3) = E(x^2 + 2x + 1 + x^2 + x + x^2) = E(3x^2 + 3x + 1) = 3E(x^2) + 3E(x) + 1.
所以我们得到了∆的表达式,那么这一位是1的概率是pi,所以需要给∆乘上pi --> E((x + 1)^3) = E((x)^3) + p[x + 1] * (3E((x) ^ 2) + 3E(x) + 1).
2>
然后我们需要计算E(x^2), E(x) 的价值,我们依然要明确这里的x是结尾连续1的长度的期望,和上面的x并不是一个意思,我们用l代替。
同样的我们假设这一位是1,那么E((l + 1)^2) = E(l^2) + ∆ --> ∆ = 2E(l) + 1
所以我们应该整个乘上p[l + 1],所以E((l + 1) ^ 2) = p[l + 1] * (E(l ^ 2) + ∆).
遇到的几个问题:
1> 首先我们需要明确 E(x^3) 这个是答案值,我们这样考虑,E(x^3) = E((x - 1)^3) + ∆。E((x - 1)^3)是不变的,我们需要给他加上新的值乘上概率,也就是说我们应该写成 E(x^3) = E((x - 1) ^ 3) + p[x] * ∆. 注意在∆前面乘上p[x],这代表着这一位的可能取值。
2> 在递推过程中,∆ = 3E((x - 1)^2) + 3E(x - 1) + 1。也就是说这一位需要的是上一位的E(x^2)和E(x)。这里的x是指长度,所以我们在解决E(x^2)的问题时,同样可以一样考虑,E(x^2) = E((x - 1) ^ 2) + ∆,但是注意这是这一位取1的值的可能取值,那么我们应该E(x^2) = p[x] * (E((x - 1)^2) + ∆).
3> 注意,1>和2>中p[x]的乘的地方是不一样的,应为一个是累加贡献,而另一个是加上以后才是这一位如果取一的取值。
4> 在解决E(x^3)的时候,如果用E(x^3) - E((x - 1) ^ 3) = 3E(x^2) - 3E(x) + 1。但是这是不一样的,应为我们在用E((x - 1)^3) 去推理 E(x^3) 所以后面应该是用3E((x - 1)^2) + 3E(x - 1) + 1.
#include <bits/stdc++.h> #define rep(i, a, b) for (int i = a; i <= b; i++) #define drep(i, a, b) for (int i = a; i >= b; i--) #define REP(i, a, b) for (int i = a; i < b; i++) #define pb push_back #define mp make_pair #define clr(x) memset(x, 0, sizeof(x)) #define xx first #define yy second using namespace std; typedef long long i64; typedef pair<int, int> pii; const int inf = ~0U >> 1; const i64 INF = ~0ULL >> 1; //*************************************** int main() { int n; scanf("%d", &n); double ans(0), l(0), l2(0), p; rep(i, 1, n) { scanf("%lf", &p); ans += p * (3 * l2 + 3 * l + 1); l2 = p * (l2 + 2 * l + 1); l = p * (l + 1); } printf("%.1lf\n", ans); return 0; }
View Code
相关文章推荐
- 关于操作系统中pv操作的实现
- 杭电ACM1021
- zhphp framework (二十八) token 加密与解密
- 异常java.lang.Thread.dumpStack(Unknown Source)
- 手把手入门神经网络系列(2)_74行代码实现手写数字识别
- C# 反射技术简介
- view的getChildMeasureSpace方法总结
- 手把手入门神经网络系列(2)_74行代码实现手写数字识别
- c语言学习笔记之static和extern关键字
- 【Redis】redis介绍-启动过程
- 数组的理解
- STM32的外部中断
- 面试总结6--C++基础问题Part2
- vc++中几个常用的数学函数
- Linux 用户管理命令
- 匿名内部类
- 解决PLSQL报错"动态执行表不可访问,本会话的自动统计被禁止"
- zhphpframework (二十七) php封装js函数
- rewrw
- Add Two Numbers