HDU-1204 糖果大战(概率DP)

版权声明:我这种蒟蒻的文章,真正的大佬一般看不上的_(:з」∠)_ https://blog.csdn.net/Paulliant/article/details/82291467

题意

两个人分别有 N , M 颗糖果,现在他们在玩 24 点,已知这两人分别想出来的概率为 p , q ,赢可以获得对方的一颗糖,当某个人糖被拿完就判输,求第一个人胜利的概率。
1 N , M 50

思路

赢的概率为 p ( 1 q ) ,输的概率为 q ( 1 p ) ,那么这两个数分别除以 p ( 1 q ) + q ( 1 p ) 就能排除和的情况。
问题就转化成了已知第一个人赢的概率为 p ,第二个人赢的概率为 q ( p + q = 1 ) ,求第一个人获胜概率。
a n 为第一个人手中有 n 个糖果的获胜概率。
a n = p a n + 1 + q a n 1 , a 0 = 0 , a N + M = 1 , 求 a N .
a n 1 = q a n + p a n 2
a n = 1 p a n 1 q p a n 2
写出特征方程 x 2 1 p x + q p = 0
x 2 1 p x + 1 p p = 0
解得 x 1 = 1 p p = q p , x 2 = 1 .
设通项为 a n = K 1 ( q p ) n + K 2 1 n a n = K 1 ( q p ) n + K 2
a 0 = K 1 + K 2 , a N + M = K 1 ( q p ) N + M + K 2
K 1 + K 2 = 0 , K 1 ( q p ) N + M + K 2 = 1
解得 K 1 = 1 ( q p ) N + M 1 , K 2 = 1 ( q p ) N + M 1
通项为 a n = ( q p ) n 1 ( q p ) N + M 1
a N = ( q p ) N 1 ( q p ) N + M 1
直接套公式解决。

代码

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define FOR(i,x,y) for(int i=(x);i<=(y);i++)
#define DOR(i,x,y) for(int i=(x);i>=(y);i--)
typedef long long LL;
using namespace std;

int main()
{
    int n,m;
    double p,q;
    while(~scanf("%d%d%lf%lf",&n,&m,&p,&q))
    {
        double P=p*(1.0-q),Q=q*(1.0-p);
        if(m==0)printf("1.00\n");
        else if(n==0)printf("0.00\n");
        else if(P==Q)printf("%.2lf\n",1.0*n/(n+m));
        else if(P==1)printf("1.00\n");
        else if(Q==1)printf("0.00\n");
        else printf("%.2lf\n",(1.0-pow(Q/P,n))/(1.0-pow(Q/P,n+m)));
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Paulliant/article/details/82291467