原创----杭电1204, 糖果大战解题报告
首先要说明几点:
- 这是一道数学题, 对学过随机过程的来说非常easy, 就是一个非常简单的Markov 过程. 不然的话会感觉无从下手, 想彻底搞明白的话,建议看看随机过程的书.
- 出题人喜欢玩儿些文字游戏, 设置了一些很无聊的陷阱, 非常无趣.
- 代码简单, 但要注意几个条件判断的顺序.
- 杭电的bbs上好像有人给出了大概的思路, 不过其中的数学公式有问题.
P00=PNN=1, 这里N = m+n
Pi, i+1=p(1-q), Pi, i-1=(1-p)q, Pi, i=1-p(1-q)-q(1-p), i=1, 2, 3...., N-1; (*)
该MC的状态有3类{0}, {1, 2, ..., N-1}, 以及{N}, 其中第二类是非常返的, 第一三类是常返的, 因为每个一非常返态通常仅到达有穷多次, 所以在进行可以在进行有穷多次博弈后, S君或者最终赢得所有糖果, 或者输掉所有糖果.
这里我们的定义fi=fiN=P(S君经过有限次博弈赢得N个糖果|X0=i), 这里fi是一个条件概率, 就是开始的时候有i个糖果, 最中赢得N个糖果的概率. 从(*)式可以知道, 当我们有在某时刻t有i个糖果, 我们可以有三种途径可以最终赢得N个糖果. 1. 赢得一个糖果, 概率是p(1-q), 这是下一个时刻t+1G君就有了i+1个糖果. 2. 输掉比赛, 在下一个时刻变成了i-1个糖果, 概率是q(1-p). 3. 打成平手, 下一个时刻还有i个糖果, 概率是1-p(1-q)-q(1-p). 这样我么就可以得到如下公式
fi=p(1-q)*fi+1+q(1-p)*fi-1+(1-p(1-q)-q(1-p))*fi
令 P=p(1-q), Q=q(1-p), K=Q/P, 则
fi+1-fi=K(fi-fi-1)
fi+1-fi是简单的等比数列, 则 fi+1-fi=Ki(f1-f0). 注意到fN=1, f0=0, 这里N=m+n;
f2-f1=Kf1
f3-f2=K2f1
................
fn-fn-1=Kn-1f1
..............
fm+n-fm+n-1=Km+n-1f1
相加一下, fn=(1+K+K2+...+Kn-1)f1, fn+m=(1+K+K2+...+Km+n-1)f1
所以fn=(1+K+K2+...+Kn-1)/(1+K+K2+...+Km+n-1), k!=1时, 可以化简为fn=(1-Kn)/(1-Km+n)
Done!
下面是个AC的代码, enjoy!
1
#include <stdio.h>
2
#include <math.h>
3
const double EPS = 1e-12;
4
5
inline void solve(int n, int m, double p, double q) {
6
if(n==0) {
7
printf("0.00\n");
8
}
9
else if(m==0) {
10
printf("1.00\n");
11
}
12
else if(p==0.0||q==1.0) {
13
printf("0.00\n");
14
}
15
else {
16
double lamda = q*(1-p)/(p*(1-q));
17
if(fabs(lamda-1.0)<EPS) {
18
printf("%.2lf\n", double(n)/(m+n));
19
}
20
else {
21
double res = (1-pow(lamda, n))/(1-pow(lamda, m+n));
22
printf("%.2lf\n", res);
23
}
24
}
25
}
26
27
int main()
28
{
29
int n, m;
30
double p, q;
31
while(scanf("%d%d%lf%lf", &n, &m, &p, &q)!=EOF) {
32
solve(n, m, p, q);
33
}
34
return 0;
35
}
#include <stdio.h>2
#include <math.h>3
const double EPS = 1e-12;4

5
inline void solve(int n, int m, double p, double q) {6
if(n==0) {7
printf("0.00\n");8
}9
else if(m==0) {10
printf("1.00\n");11
}12
else if(p==0.0||q==1.0) {13
printf("0.00\n");14
}15
else {16
double lamda = q*(1-p)/(p*(1-q));17
if(fabs(lamda-1.0)<EPS) {18
printf("%.2lf\n", double(n)/(m+n));19
}20
else {21
double res = (1-pow(lamda, n))/(1-pow(lamda, m+n));22
printf("%.2lf\n", res);23
}24
}25
}26

27
int main()28
{29
int n, m;30
double p, q;31
while(scanf("%d%d%lf%lf", &n, &m, &p, &q)!=EOF) {32
solve(n, m, p, q);33
}34
return 0;35
}

inline 
浙公网安备 33010602011771号