前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SP4060 KPGAME - A game with probability

SP4060 KPGAME - A game with probability

作者头像
yzxoi
发布2022-09-19 14:12:00
4120
发布2022-09-19 14:12:00
举报
文章被收录于专栏:OI

SP4060 KPGAME - A game with probability

题目链接:SP4060

Alice和Bob在玩一个游戏。

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

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

T\leq 50, n\leq 10^8, 0.5\leq p,q < 1

Tutorial

不妨设 dp[i][0/1] 表示目前是 Alice/Bob 投掷硬币,还剩 i 个石子,Alice 胜利的概率。

显然有 dp[0][0]=1, dp[0][1]=0。转移的话需要分两类情况讨论:

dp[i-1][0] > dp[i-1][1]i-1 个石子时,若轮到 Alice 投掷硬币,Alice 获胜的概率更大,因此 Alice 因想尽办法尽可能在剩余第 i 个石子时,投掷反面,让 Bob 拿走第 i 颗石子。Bob 为了让 Alice 尽可能输,因此他希望在剩余 i 个石子时,他能够投掷反面,让 Alice 拿走第 i 颗石子。

同理,若 dp[i-1][0] < dp[i-1][1]i 颗石子。

因此,我们可以列出转移方程。

\begin{aligned}dp[i][0] = dp[i-1][1] \times p + dp[i][1] \times (1-p)\\dp[i][1] = dp[i-1][0] \times q + dp[i][0] \times (1-q)\end{aligned}

其中,p,qdp[i-1][0] < dp[i-1][1]A,B,否则为 1-A,1-B

注意到当 i 增大的同时,dp 数组的值会不断减小,因此之后可以忽略不记,所以可以将 n1000\min 即可通过本题。

当然,如果你感觉比较好,会发现 p,q 的取值与 i 的奇偶性有关,因此可以两步一起跑,矩阵快速幂加速转移即可。

复杂度 O(TN\log N)

Solution

代码语言:javascript
复制
#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define W while
#define I inline
#define RI register int
#define LL long long
#define Cn const
#define CI Cn int&
#define gc getchar
#define D isdigit(c=gc())
#define pc(c) putchar((c))
#define min(x,y) ((x)<(y)?(x):(y))
#define max(x,y) ((x)>(y)?(x):(y))
using namespace std;
namespace Debug{
	Tp I void _debug(Cn char* f,Ty t){cerr<<f<<'='<<t<<endl;}
	Ts I void _debug(Cn char* f,Ty x,Ar... y){W(*f!=',') cerr<<*f++;cerr<<'='<<x<<",";_debug(f+1,y...);}
	Tp ostream& operator<<(ostream& os,Cn vector<Ty>& V){os<<"[";for(Cn auto& vv:V) os<<vv<<",";os<<"]";return os;}
	#define gdb(...) _debug(#__VA_ARGS__,__VA_ARGS__)
}using namespace Debug;
namespace FastIO{
	Tp I void read(Ty& x){char c;int f=1;x=0;W(!D) f=c^'-'?1:-1;W(x=(x<<3)+(x<<1)+(c&15),D);x*=f;}
	Ts I void read(Ty& x,Ar&... y){read(x),read(y...);}
	Tp I void write(Ty x){x<0&&(pc('-'),x=-x,0),x<10?(pc(x+'0'),0):(write(x/10),pc(x%10+'0'),0);}
	Tp I void writeln(Cn Ty& x){write(x),pc('\n');}
}using namespace FastIO;
Cn int N=1e6+10;
int Tt,n;double A,B,f[N][2],p,q;
int main(){
	RI i;read(Tt);W(Tt--){
		for(read(n),scanf("%lf%lf",&A,&B),assert(0.5<=A&&A<=1&&0.5<=B&&B<=1),f[0][0]=0,f[0][1]=1,i=1;i<=min(n,1000);i++)
			f[i-1][1]>f[i-1][0]?(p=A,q=B):(p=1-A,q=1-B),f[i][0]=(f[i-1][0]*q*(1-p)+f[i-1][1]*p)/(1-(1-q)*(1-p)),f[i][1]=f[i][0]*(1-q)+f[i-1][0]*q;
		printf("%.6lf\n",f[min(n,1000)][0]);
	}return 0;
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-07-09 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • SP4060 KPGAME - A game with probability
    • Tutorial
      • Solution
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档