题目描述

Alice和Bob在玩一个游戏。有n个石子在这里,Alice和Bob轮流投掷硬币,如果正面朝上,则从n个石子中取出一个石子,否则不做任何事。取到最后一颗石子的人胜利。Alice在投掷硬币时有p的概率投掷出他想投的一面,同样,Bob有q的概率投掷出他相投的一面。

现在Alice先手投掷硬币,假设他们都想赢得游戏,问你Alice胜利的概率为多少。

输入

第一行一个正整数t,表示数据组数。

对于每组数据,一行三个数n,p,q。

输出

对于每组数据输出一行一个实数,表示Alice胜利的概率,保留6位小数。

样例输入

1
1 0.5 0.5

样例输出

0.666667

提示

数据范围:
1<=t<=50
0.5<=p,q<=0.99999999
对于100%的数据 1<=n<=99999999

题解

概率dp

这题真是巨坑。。。

f[i]表示i块石头先投者获胜的概率,g[i]表示i块石头后投者获胜的概率。

易推出:

$f[i]=\frac{p_0·g[i-1]+(1-p_0)·q_0·f[i-1]}{1-(1-p_0)·(1-q_0)}$

$g[i]=\frac{q_0·f[i-1]+(1-q_0)·p_0·g[i-1]}{1-(1-p_0)·(1-q_0)}$

然而这里$p_0$和$q_0$都是目标概率,而题目中的p和q都是几率,

所以需要根据情况决定是否想要正面朝上。

根据方程的推导:

A想让自己获胜的概率最大,即让$f[i]$最大。

假设$g[i-1]-f[i-1]$不等于$0$,把$f[i]$的推导式展开,得:

$f[i]=\frac{p_0·g[i-1]+(1-p_0)·q_0·f[i-1]}{1-(1-p_0)·(1-q_0)}\\\ \ \ \ \ \ =\frac{(p_0+q_0-p_0·q_0)·f[i-1]+p_0(g[i-1]-f[i-1])}{p_0+q_0-p_0·q_0}\\\ \ \ \ \ \ =f[i-1]+\frac{p_0(g[i-1]-f[i-1])}{p_0+q_0-p_0·q_0}\\\ \ \ \ \ \ =f[i-1]+\frac1{\frac{p_0+q_0-p_0·q_0}{p_0(g[i-1]-f[i-1])}}\\\ \ \ \ \ \ =f[i-1]+\frac1{\frac{1-q_0+\frac{q_0}{p_0}}{g[i-1]-f[i-1]}}$

显然当$g[i-1]-f[i-1]>0$时,$p_0$越大越好;当$g[i-1]-f[i-1]<0$时,$p_0$越小越好。

$q_0$的推导同理。

于是可以得到结论:

当f[i-1]<g[i-1]时,都想要正面朝上,$p_0=p$,$q_0=q$;

当f[i-1]>g[i-1]时,都不想要正面朝上,$p_0=1-p$,$q_0=1-q$。

但是n太大肿么办?

于是用到概率黑科技:

当n越来越大时,f[n]逐渐趋近于一个定值,而且题目中只要求保留6位小数。

所以就此题而言f[1000+k]可以近似等于f[1000]。

于是时间复杂度就降为O(1000T),可解。

#include <cstdio>
#include <cstring>
double f[1001] , g[1001];
int main()
{
int t;
scanf("%d" , &t);
while(t -- )
{
int n , i;
double p , q;
scanf("%d%lf%lf" , &n , &p , &q);
memset(f , 0 , sizeof(f));
memset(g , 0 , sizeof(g));
if(n > 1000)
n = 1000;
f[0] = 0;
g[0] = 1;
for(i = 1 ; i <= n ; i ++ )
{
if(f[i - 1] > g[i - 1])
p = 1 - p , q = 1 - q;
f[i] = (p * g[i - 1] + (1 - p) * q * f[i - 1]) / (1 - (1 - p) * (1 - q));
g[i] = (q * f[i - 1] + (1 - q) * p * g[i - 1]) / (1 - (1 - p) * (1 - q));
if(f[i - 1] > g[i - 1])
p = 1 - p , q = 1 - q;
}
printf("%.6lf\n" , f[n]);
}
return 0;
}

【bzoj2318】Spoj4060 game with probability Problem的更多相关文章

  1. 【BZOJ2318】Spoj4060 game with probability Problem 概率

    [BZOJ2318]Spoj4060 game with probability Problem Description Alice和Bob在玩一个游戏.有n个石子在这里,Alice和Bob轮流投掷硬 ...

  2. 【bzoj2318】Spoj4060 game with probability Problem 概率dp

    题目描述 Alice和Bob在玩一个游戏.有n个石子在这里,Alice和Bob轮流投掷硬币,如果正面朝上,则从n个石子中取出一个石子,否则不做任何事.取到最后一颗石子的人胜利.Alice在投掷硬币时有 ...

  3. 【BZOJ 2318】 2318: Spoj4060 game with probability Problem(概率DP)

    2318: Spoj4060 game with probability Problem Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 371  Sol ...

  4. BZOJ2318: Spoj4060 game with probability Problem

    #include<iostream> #include<algorithm> #include<cstring> #include<cstdio> #i ...

  5. BZOJ 2318: Spoj4060 game with probability Problem( 概率dp )

    概率dp... http://blog.csdn.net/Vmurder/article/details/46467899 ( from : [辗转山河弋流歌 by 空灰冰魂] ) 这个讲得很好 , ...

  6. 【CF954I】Yet Another String Matching Problem(FFT)

    [CF954I]Yet Another String Matching Problem(FFT) 题面 给定两个字符串\(S,T\) 求\(S\)所有长度为\(|T|\)的子串与\(T\)的距离 两个 ...

  7. 2318: Spoj4060 game with probability Problem

    2318: Spoj4060 game with probability Problem Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 356  Sol ...

  8. Bzoj 2318 Spoj4060 game with probability Problem

    2318: Spoj4060 game with probability Problem Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 524  Sol ...

  9. 【概率论】2-1:条件概率(Conditional Probability)

    title: [概率论]2-1:条件概率(Conditional Probability) categories: Mathematic Probability keywords: Condition ...

随机推荐

  1. 一个开关电源传导、辐射处理案例-----Layout环路

    这是一款输入宽电压120-277V  60HZ,输出48V,273mA的电源,使用美芯晟MT7933,采用Buck拓扑结构. 注:在最初的设计中,预留电感L1.L2,CBB电容C1.C2作为传导测试元 ...

  2. GCC 中零长数组与变长数组

    前两天看程序,发现在某个函数中有下面这段程序: int n; //define a variable n int array[n]; //define an array with length n 在 ...

  3. 闪电动画模拟(Dielectric Breakdown Model)附源码

    当两个物体之间存在较大的电势差时会出现放电现象,比如生活中常见的闪电现象,闪电形成的条件就是云层积累了大量负电荷之后与地面之间形成了强大的电势差.目前关于闪电建模的方法比较少,下面介绍一种利用电介击穿 ...

  4. intel和AMD CPU性能对比(2016年CPU天梯图)组装电脑必读!

    http://www.365pcbuy.com/article-411.html 特别提示:此文已经于2016年10月12日更新!内容变动较大,请细细品鉴! 如何为客户推荐高性价比机型是我站的重要工作 ...

  5. C#.NET 大型通用信息化系统集成快速开发平台 4.1 版本 - 角色成员功能的改进支持公司加入到角色

    我们公司有1万多个网点,每个网点都可以看成是一个公司,公司对不同的网点有不同的策略,商业逻辑,每个网点的人员也都是在不断变化,全国有接近10万从业人员,当我们设计好业务逻辑程序后,不可能因为这些人员的 ...

  6. oracle的decode函数在mysql的实现

    oracle中的decode函数很好用,换成mysql中可以用类似下面的方法实现: SELECT IF(TRUE, '真值', '假值'); 如果想再弄复杂点,可以多个IF嵌套,不过嵌套的层次多了,代 ...

  7. .net ServiceStack.Redis 性能调优

    最近在debug生产环境的问题时,发现了ServiceStack 4.0.60版本RedisClient存在一个非常严重的性能问题.在高并发下,PooledRedisClientManager.Get ...

  8. 【分享】仿东软OA协同办公服务管理源码

    功能列表: 1.个人办公管理: 内部邮件.消息管理.手机短信.公告通知.新闻管理.投票管理.个人考勤 日程安排:我的安排.下属安排 工作日志:我的日志.日志查询.日志设置 工作汇报:我的汇报.下属汇报 ...

  9. JavaScript模板引擎artTemplate.js——template()方法

    template(id, data)方法: id:必传,渲染模板的id. data:可选,一个Object对象. return:传data—>渲染完成html代码:不传data—>一个渲染 ...

  10. 开发错误记录13:java.lang.UnsatisfiedLinkError: Couldn't load xxx.so: findLibrary returned null

    今天在导入环信开发包时,编译报如下错: java.lang.UnsatisfiedLinkError: Couldn't load hyphenate_av from loader dalvik.sy ...