LightOj_1274 Beating the Dataset
题意:
给一个文档, 这个文档由yes 、no 组成, 共有s个byte, 共有n个yes、no。
假设yes的个数为yes_num, no的个数为no_num。
将这n个数进行排列, 对于每个排列, 将其右移一个结果, 并在最左端补上yes, 再将其与原排列进行对比, 看有多少个不同的。
计算所有排列中 不同结果的平均次数。
思路:
可能题意说的不是很清楚, 这里抽象一下, 将yes用1代替, no用0代替。
当n = 3, s = 7时, 也就是2个0 一个1, 有下面三种排列
100, 010, 001
对于每种排列的处理:
100
110 不同的只有一个, 有三种情况, 每种情况抽中的概率是1/3 所以 当前情况的期望就是 1/3 * 1
010
101 不同的有三个, 当前情况的期望是1/3 * 3
001
100 不同的有两个,当前情况的期望是1/3 * 2
so, 总的期望就是1/3 * (1+3+2) = 6 / 3 = 2
将原排列进行整理下, 会发现一个现象。
每种排列的次数就是原排列中有多少个相邻不同的数字, 如果最左端是0, 那么还要 + 1 (因为左端要补上1, 和0 不同 所以要加1)
此时可以发现, 当前状态的期望数其实和上一状态是有关系的。
假设dp[i][j][flag]为当前为第i位, 前面有j个1(yes), 上一状态(第i + 1 位) 是flag(0 == no, 1 == yes)。
那么, flag 要么为0, 要么为一, 也即 第i + 1位的状态。
{……j 个 yes……} flag k {…………}, k为第i + 2 位的状态。
dp[i][j][flag] = (dp[i+1][j][0] + (flag != 0))* p_no + (dp[i + 1][j + 1] + (flag != 1)) * p_yes.
也有大神推出公式了, 不过在下实在推不出来 囧 坐等大神解答。
公式:(2.0 * yes_num * no_num + no_num)/(yes_num + no_num)
加一段递归代码用以理解状态转移方程。
- double dp(int n, int y, int a)
- {
- if (n == ) // There are no options to choose
- return ;
- double p_no = (n - y) / (double) n;
- double p_yes = y / (double) n;
- double ans = ;
- if (y < n)
- ans += (dp(n - , y, ) + (a != )) * p_no;
- if (y > )
- ans += (dp(n - , y - , ) + (a != )) * p_yes;
- return ans;
- }
代码:
- #include <cmath>
- #include <cstdio>
- #include <cstring>
- #include <cstdlib>
- #include <ctime>
- #include <set>
- #include <map>
- #include <list>
- #include <queue>
- #include <string>
- #include <vector>
- #include <fstream>
- #include <iterator>
- #include <iostream>
- #include <algorithm>
- using namespace std;
- #define LL long long
- #define INF 0x3f3f3f3f
- #define MOD 1000000007
- #define eps 1e-6
- #define MAXN 5050
- int n, s;
- double dp[][MAXN][];// 0 --> NO, 1 --> yes
- int yes_num, no_num;
- int kcase = ;
- void solve()
- {
- memset(dp, , sizeof(dp));
- yes_num = s - * n;
- no_num = n - yes_num;
- for(int i = ; i <= n + ; i ++)
- for(int j = ; j <= min(i, yes_num); j ++)
- {
- double p_yes = j * 1.0 / i;
- double p_no = (i - j) * 1.0 / i;
- if(j - >= )
- {
- dp[i % ][j][] = dp[(i + ) % ][j - ][] * p_yes + (dp[(i + ) % ][j][] + 1.0) * p_no;
- dp[i % ][j][] = (dp[(i + ) % ][j - ][] + 1.0) * p_yes + dp[(i + ) % ][j][] * p_no;
- }
- else
- {
- dp[i % ][j][] = (dp[(i + ) % ][j][] + 1.0) * p_no;
- dp[i % ][j][] = dp[(i + ) % ][j][] * p_no;
- }
- }
- printf("Case %d: %.7lf\n", ++kcase, dp[n % ][yes_num][]);
- }
- void solve_()
- {
- memset(dp, , sizeof(dp));
- yes_num = s - * n;
- no_num = n - yes_num;
- for(int i = n - ; i >= ; i --)
- for(int j = min(i, yes_num); j >= && (i - j <= no_num); j --)
- {
- double p_yes = (yes_num - j) * 1.0 / (n - i);
- double p_no = (no_num - (i - j)) * 1.0 / (n - i);
- if(j + <= yes_num)
- {
- dp[i % ][j][] = (dp[(i + ) % ][j + ][] + 1.0) * p_yes + dp[(i + ) % ][j][] * p_no;
- dp[i % ][j][] = dp[(i + ) % ][j + ][] * p_yes + (dp[(i + ) % ][j][] + 1.0) *p_no;
- }
- else
- {
- dp[i % ][j][] = p_yes + dp[(i + ) % ][j][] * p_no;
- dp[i % ][j][] = (dp[(i + ) % ][j][] + 1.0) *p_no;
- }
- }
- printf("Case %d: %.7lf\n", ++kcase, dp[][][]);
- }
- int main()
- {
- int T;
- scanf("%d", &T);
- while(T --)
- {
- scanf("%d %d", &n, &s);
- solve_();
- }
- return ;
- }
LightOj_1274 Beating the Dataset的更多相关文章
- LightOJ - 1274 Beating the Dataset —— 期望
题目链接:https://vjudge.net/problem/LightOJ-1274 1274 - Beating the Dataset PDF (English) Statistics ...
- 【非原创】LightOJ-1274 Beating the Dataset【期望dp】
学习博客:戳这里
- KUANGBIN带你飞
KUANGBIN带你飞 全专题整理 https://www.cnblogs.com/slzk/articles/7402292.html 专题一 简单搜索 POJ 1321 棋盘问题 //201 ...
- kuangbin 带你飞 概率期望
正推不行就逆推! 经典问题:生日悖论 换成其互斥事件:m个人, 每个人生日都不相同的概率 ≤ 0.5 时最小人数. 这就是邮票收集问题的变形:每个邮票至少出现一次的概率 小于等于 0.5 邮票收集问题 ...
- [kuangbin带你飞]专题1-23题目清单总结
[kuangbin带你飞]专题1-23 专题一 简单搜索 POJ 1321 棋盘问题POJ 2251 Dungeon MasterPOJ 3278 Catch That CowPOJ 3279 Fli ...
- ACM--[kuangbin带你飞]--专题1-23
专题一 简单搜索 POJ 1321 棋盘问题POJ 2251 Dungeon MasterPOJ 3278 Catch That CowPOJ 3279 FliptilePOJ 1426 Find T ...
- HTML5 数据集属性dataset
有时候在HTML元素上绑定一些额外信息,特别是JS选取操作这些元素时特别有帮助.通常我们会使用getAttribute()和setAttribute()来读和写非标题属性的值.但为此付出的代价是文档将 ...
- C#读取Excel,或者多个excel表,返回dataset
把excel 表作为一个数据源进行读取 /// <summary> /// 读取Excel单个Sheet /// </summary> /// <param name=& ...
- DataTable DataRow DataColumn DataSet
1.DataTable 数据表(内存) 2.DataRow DataTable 的行 3.DataColumn DataTable 的列 4.DataSet 内存中的缓存
随机推荐
- Python调用C可执行程序(subprocess) 分类: python 服务器搭建 C/C++ shell 2015-04-13 21:03 87人阅读 评论(0) 收藏
从Python 2.4开始,Python引入subprocess模块来管理子进程,以取代一些旧模块的方法:如 os.system.os.spawn.os.popen.popen2.commands. ...
- 1032 - Intersecting Dates
A research group is developing a computer program that will fetch historical stock market quotes fro ...
- 第一个Xcode项目 - 代码修改布局约束
第一行的选中效果已经有了,那第二行的选中效果怎么做呢?我这里选择改变布局约束来实现选中效果 [我有个用object-c做APP的同事他说,我觉得这个应该去获取色块的位置,然后赋给选中用的View,然后 ...
- STM32的优先级NVIC_PriorityGroupConfig的理解及其使用
写作原由:因为之前有对stm32 优先级做过研究,但是没时间把整理的东西发表,最近项目需要2个串口,但是不是两个串口同时使用,只是随机使用其中一个,程序对2个串口的优先级需要配置: 此文思路:“中断优 ...
- git的一些基础命令
Git常用命令 请确保已经安装里git客户端 一般配置 git --version //查看git的版本信息 git config --global user.name //获取当前登录的用户 git ...
- JS获取图片上传地址
function getObjectURL(file) { var url = null ; if (window.createObjectURL!=undefined) { // basic url ...
- ubuntu15.10下sublime text3 无法输入中文解决办法
原文链接:http://geek.csdn.net/news/detail/44464 1.首先保证你的电脑有c++编译环境 如果没有,通过以下指令安装 sudo apt-get install bu ...
- 使用微信js接口的方法 ,以调用相机为例
protected string GetTimeStamp_Str=""; protected string nonceStr_Str = ""; protec ...
- asp.net 调用前台JS调用后台,后台掉前台JS
C#前台js调用后台代码前台js<script type="text/javascript" language="javascript"> func ...
- JQM 页面滚动加载
1 应用场景:文章比较长,只加载部分,当到页面底部触发获取更多数据. 2 如图,监听滚动条的位置,触发事件,转化为求X的长度, 3 实例代码: //滚动条到底加载更多 $(document).on(& ...