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

题意

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

思路

赢的概率为 p(1q) p ( 1 − q ) ,输的概率为 q(1p) q ( 1 − p ) ,那么这两个数分别除以 p(1q)+q(1p) p ( 1 − q ) + q ( 1 − p ) 就能排除和的情况。
问题就转化成了已知第一个人赢的概率为 p p ​ ,第二个人赢的概率为 q q ​ (p+q=1) ( p + q = 1 ) ​ ,求第一个人获胜概率。
an a n 为第一个人手中有 n n 个糖果的获胜概率。
an=pan+1+qan1, a0=0 a 0 = 0 , aN+M=1 a N + M = 1 , 求 aN a N .
an1=qan+pan2 a n − 1 = q a n + p a n − 2
an=1pan1qpan2 a n = 1 p a n − 1 − q p a n − 2
写出特征方程 x21px+qp=0 x 2 − 1 p x + q p = 0
x21px+1pp=0 x 2 − 1 p x + 1 − p p = 0
解得 x1=1pp=qp x 1 = 1 − p p = q p , x2=1 x 2 = 1 .
设通项为 an=K1(qp)n+K21n a n = K 1 ( q p ) n + K 2 1 n an=K1(qp)n+K2 a n = K 1 ( q p ) n + K 2
a0=K1+K2,aN+M=K1(qp)N+M+K2 a 0 = K 1 + K 2 , a N + M = K 1 ( q p ) N + M + K 2
K1+K2=0,K1(qp)N+M+K2=1 K 1 + K 2 = 0 , K 1 ( q p ) N + M + K 2 = 1
解得 K1=1(qp)N+M1,K2=1(qp)N+M1 K 1 = 1 ( q p ) N + M − 1 , K 2 = − 1 ( q p ) N + M − 1
通项为 an=(qp)n1(qp)N+M1 a n = ( q p ) n − 1 ( q p ) N + M − 1
aN=(qp)N1(qp)N+M1 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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值