Bob有q的概率投掷出她相投的3只,阿丽丝在投标硬币时有p的票房价值投掷出他想投的单方面

2318: Spoj4060 game with probability Problem

Time Limit: 1 Sec  Memory
Limit: 128 MB
Submit: 524  Solved: 262
[Submit][Status][Discuss]

Source

图片 1

对于上边这一个读者或许不知情,

发端作者也不精通前边想了须臾间很巧妙啊,

因为f[i-1]>g[i-1]的话先手动和自动然不想选,选了变成g[i-1]<f[i-1]那不是家常便饭;

那正是说对于后手来说变成了f[i-1],就一定于g[i]*p (p<1)
f[i-1]<g[i]

但是作者不选的话依旧g[i],且g[i]>f[i-1],分明二者为了利益都不会去选,前面都想选评释同理!

图片 2

#include<cstdio>
#include<iostream>
using namespace std;
const int N=1005;
int T,n;
double p,q,f[N],g[N];
//有点卡精度。乘了无数个1.0 
inline void dp(){
    n=min(n,1000);
    f[0]=0;g[0]=1;
    for(int i=1;i<=n;i++){
        if(f[i-1]>g[i-1]) p=1-p,q=1-q;
        f[i]=(1.0*p*g[i-1]+1.0*(1-p)*q*f[i-1])/(1.0-1.0*(1-p)*(1-q));
        g[i]=(1.0*q*f[i-1]+1.0*(1-q)*p*g[i-1])/(1.0-1.0*(1-p)*(1-q));
        if(f[i-1]>g[i-1])p=1-p,q=1-q;
    }
    printf("%0.6lf\n",f[n]);
}
int main(){
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);scanf("%lf%lf",&p,&q);
        dp();
    }
    return 0;
}

 

Output

对此每组数据输出一行一个实数,表示Iris胜利的可能率,保留五人小数。

Input

先是行四个正整数t,表示数据组数。

对此每组数据,一行八个数n,p,q。

 

 

Sample Input

1

1 0.5 0.5

Description

艾丽丝和Bob在玩3个游戏。有n个石子在此地,艾丽丝和Bob轮流投掷硬币,假诺正面朝上,则从n个石子中取出二个砾石,不然不做任何事。取到最后一颗石子的人征服。Alice在投标硬币时有p的可能率投掷出她想投的一边,同样,鲍伯有q的票房价值投掷出他相投的一面。

现行反革命艾丽丝先手投掷硬币,如若他们都想赢得游戏,问您阿丽丝胜利的票房价值为多少。

Sample Input

1

1 0.5 0.5

Input

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

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

 

 

Sample Output

0.666667

HINT

 

数据范围:

1<=t<=50

0.5<=p,q<=0.99999999

对于100%的数据 1<=n<=99999999

  一道无比有趣的概率题……

  我们设f[i]为当下有i张牌且大家眼下所针对人物为先手的出奇制胜可能率,g[i]为退路征服可能率。

  那么,大家先考虑一下采纳希望翻正面包车型大巴概率的递推式。

    f[i]=p*g[i-1]+(1-p)*g[i]

  因为大家有p的概率将眼下范围改为退路、场上有i-1张牌,1-p的可能率将规模改为g[i]之所以大家上述递推式正确的。g[i]也是那般。

    g[i]=q*f[i-1]+(1-q)*f[i]

  为啥那里成为q呢?因为近来大家盼望翻正面一定是因为g[i-1]>f[i-1],而那个可能率对于何人都以如出一辙的,所以bob也一定是想要去翻正面,所以改为q。

  尽管那样我们好像依旧不可能推出来啊。所以大家要去解一下方程组,反正不正是二个二元1回啊?手解一下不就好了,应该不要高斯消元吧……

  至于希望翻反面,请读者本身考虑,答案就在代码里(当然不是土生土长状态呀)。

  有意思的是尽管他的n相当大,但是他并未对精度必要太高,所以大家只要等到他的精度卡到一定程度直接跳出就好了。

  小编一开头是直接判断精度,可是貌似T了,所以看别人算到一千就行了……

图片 3图片 4

 1  
 2 #include <iostream>
 3 #include <cstdlib>
 4 #include <cstdio>
 5 #include <cstring>
 6 #include <algorithm>
 7 #include <cmath>
 8 #include <queue>
 9 #include <map>
10 #include <set>
11 #include <vector>
12 #define N 1005
13 using namespace std;
14 int t,n;
15 double p,q,f[N],g[N];
16 int main()
17 {
18     scanf("%d",&t);
19 while(t--)
20 {
21     scanf("%d%lf%lf",&n,&p,&q);
22     memset(f,0,sizeof(f));
23     memset(g,0,sizeof(g));
24     g[0]=1;
25     n=min(n,1000);
26     for(int i=1;i<=n;i++)
27     {
28         if(f[i-1]<g[i-1])
29         {
30             f[i]=(p*g[i-1]+(1.0-p)*q*f[i-1])/(p+q-p*q);
31             g[i]=(q*f[i-1]+(1.0-q)*p*g[i-1])/(p+q-p*q); 
32         }
33         else
34         {
35             f[i]=(p*(1.0-q)*f[i-1]+(1.0-p)*g[i-1])/(1.0-p*q);
36             g[i]=((1.0-q)*f[i-1]+q*(1.0-p)*g[i-1])/(1.0-p*q);
37         }
38          
39     }
40     printf("%.6lf\n",f[n]);
41 }
42     return 0;
43 }

View Code

 

  

HINT

 

多少范围:

1<=t<=50

0.5<=p,q<=0.99999999

对于100%的数据 1<=n<=99999999

 

Input

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

对此每组数据,一行多个数n,p,q。

Description

Iris和Bob在玩一个游乐。有n个石子在此地,Alice和鲍伯轮流投掷硬币,假诺正面朝上,则从n个石子中取出3个石子,不然不做别的交事务。取到最后一颗石子的人克服。Alice在投标硬币时有p的概率投掷出她想投的另一方面,同样,鲍勃有q的可能率投掷出他相投的单向。

到现在Iris先手投掷硬币,要是他们都想获取游戏,问您Iris胜利的可能率为多少。

 

 

Sample Output

0.666667

2318: Spoj4060 game with probability Problem

Output

对于每组数据输出一行2个实数,表示Alice胜利的票房价值,保留6位小数。

 

 

2318: Spoj4060 game with probability Problem

Time Limit: 1 Sec  Memory
Limit: 128 MB
Submit: 356  Solved: 164
[Submit][Status][Discuss]

Sample Input

1

1 0.5 0.5

Sample Output

0.666667

Output

对此每组数据输出一行2个实数,表示艾丽丝胜利的可能率,保留陆位小数。

 

 

HINT

数量范围:

1<=t<=50

0.5<=p,q<=0.99999999

对于100%的数据 1<=n<=99999999


传送门

 

概率dp的有的简单写,博弈论的方针没想出来。

设$f[i]$表示有$i$枚石子,先手获胜的概率;

   $g[i]$表示有$i$枚石子,后手战胜的票房价值;

则当有$i+1$枚石鸡时:

  若$f[i]>g[i]$,则$Iris$希望在有$i$枚石卯时获得先手,那么她期望那轮不取;

  不然,$Alice$希望这轮获得石子;

当艾丽丝希望收获石虎时:

  若Iris在本轮中先手,则有$p$的概率在下轮取得后手,有$1-p$的票房价值在本轮取得后手;

  若Iris在本轮中后手,则有$q$的可能率在下轮取得先手,有$1-q$的几率在本轮取得先手;

即$$\begin{cases}f_i=p*g_{i-1}+(1-p)*g_i\\g_i=q*f_{i-1}+(1-q)*f_i\end{cases}$$

化简得$$f_i=\frac{p*g_{i-1}+(1-p)*q*f_{i-1}}{1-(1-p)*(1-q)}$$

$$g_i=\frac{q*f_{i-1}+(1-q)*p*g_{i-1}}{1-(1-p)*(1-q)}$$

当Iris不期望得到石未时:$p$和$(1-p)$ $q$和$(1-q)$取反即可

 

倒推dp即可。

有四个注意的点:

  n相当大,数组肯定是装不下的,显明要用滚动数组。

  O(n)的时刻复杂度显明是跑可是的,打表能够窥见答案是泯灭的,n不小的时候前7位小数已经稳定了,n取min(n,100)就好。如同是个科学普及的覆辙,照旧too
young,见得不够多。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define foru(i,x,y) for(int i=x;i<=y;i++)
 4 using namespace std;
 5 int T,n,fl;
 6 double f[2],g[2],p,q,p_,q_;
 7 int main(){
 8     scanf("%d",&T);
 9     while(T--){
10         scanf("%d%lf%lf",&n,&p,&q);
11         n=min(n,100);
12         f[0]=0;g[0]=1;q_=1-q;p_=1-p;
13         int i=1;
14         foru(j,1,n){
15             if(f[i^1]>g[i^1])swap(p_,p),swap(q_,q),fl=1;
16                 f[i]=(p*g[i^1]+p_*q*f[i^1])/(1-q_*p_);
17                 g[i]=(q*f[i^1]+q_*p*g[i^1])/(1-q_*p_);
18             if(fl==1)swap(p_,p),swap(q_,q),fl=0;i^=1;
19         }
20         printf("%.6lf\n",f[i^1]);
21     }
22 }

 

Description

Alice和鲍勃在玩八个游玩。有n个石子在此间,阿丽丝和鲍伯轮流投掷硬币,假诺正面朝上,则从n个石子中取出3个石子,否则不做任何事。取到最终一颗石子的人克制。艾丽丝在投标硬币时有p的可能率投掷出她想投的一边,同样,鲍勃有q的票房价值投掷出他相投的一端。

现行反革命Iris先手投掷硬币,假若他们都想取得游戏,问您Iris胜利的票房价值为多少。

 

 

相关文章