题目:
https://zoj.pintia.cn/problem-sets/91827364500/problems/91827368253
有三个骰子,面值分别是
1
1
1到
k
1
k_1
k1,
1
1
1到
k
2
k_2
k2,
1
1
1到
k
3
k_3
k3,扔到的概率等可能。每轮扔三个骰子,扔出的值之和加到
a
n
s
ans
ans上,当遇到
k
1
=
a
,
k
2
=
b
,
k
3
=
c
k1=a,k2=b,k3=c
k1=a,k2=b,k3=c时,
a
n
s
=
0
ans=0
ans=0重新开始累加,当
a
n
s
>
n
ans>n
ans>n时停止。问停止时轮数的期望。
0
≤
n
≤
500
;
1
<
K
1
,
K
2
,
K
3
≤
6
;
1
≤
a
≤
K
1
;
1
≤
b
≤
K
2
,
1
≤
c
≤
K
3
0\le n\le 500;1<K_1, K_2, K_3\le 6;1\le a\le K_1;1\le b\le K_2,1\le c\le K3
0≤n≤500;1<K1,K2,K3≤6;1≤a≤K1;1≤b≤K2,1≤c≤K3
思路:
令
f
(
i
)
f(i)
f(i)表示从分数为
i
i
i时到停止时的期望,边界值
f
(
i
)
=
0
(
i
>
n
)
f(i)=0(i>n)
f(i)=0(i>n),
P
P
P表示扔到
a
,
b
,
c
a,b,c
a,b,c的概率(
P
=
1
k
1
k
2
k
3
P=\frac{1}{k_1k_2k_3}
P=k1k2k31),
p
j
p_j
pj表示扔到
j
j
j分的概率(不包含
a
,
b
,
c
a,b,c
a,b,c这种情况),有
f
(
i
)
=
1
+
P
f
(
0
)
+
∑
j
=
3
k
1
+
k
2
+
k
3
p
j
f
(
i
+
j
)
(
i
>
n
时
,
反
正
f
(
i
)
=
0
)
\begin{aligned} f(i)&=1+Pf(0)+\sum_{j=3}^{k_1+k_2+k_3}p_jf(i+j)\quad(i>n时,反正f(i)=0)\\ \end{aligned}
f(i)=1+Pf(0)+j=3∑k1+k2+k3pjf(i+j)(i>n时,反正f(i)=0)
f
(
0
)
f(0)
f(0)就是要求的,发现会成环,但是如果先不考虑
f
(
0
)
=
1
+
P
f
(
0
)
+
∑
j
p
j
f
(
j
)
f(0)=1+Pf(0)+\sum_{j}p_jf(j)
f(0)=1+Pf(0)+∑jpjf(j),可以看成初始值为
f
(
0
)
f(0)
f(0)的一个递推数列。所以可以求出通项公式。
设
f
(
i
)
=
A
(
i
)
f
(
0
)
+
B
(
i
)
f(i)=A(i)f(0)+B(i)
f(i)=A(i)f(0)+B(i)(因为是线性的),代入得
A
(
i
)
f
(
0
)
+
B
(
i
)
=
1
+
P
f
(
0
)
+
∑
j
=
3
k
1
+
k
2
+
k
3
p
j
[
A
(
i
+
j
)
f
(
0
)
+
B
(
i
+
j
)
]
A
(
i
)
f
(
0
)
+
B
(
i
)
=
1
+
f
(
0
)
(
P
+
∑
j
=
3
k
1
+
k
2
+
k
3
p
j
A
(
i
+
j
)
)
+
∑
j
p
j
B
(
i
+
j
)
{
A
(
i
)
=
P
+
∑
j
=
3
k
1
+
k
2
+
k
3
p
j
A
(
i
+
j
)
可
以
递
推
求
B
(
i
)
=
1
+
∑
j
=
3
k
1
+
k
2
+
k
3
p
j
B
(
i
+
j
)
\begin{aligned} A(i)f(0)+B(i)&=1+Pf(0)+\sum_{j=3}^{k_1+k_2+k_3}p_j[A(i+j)f(0)+B(i+j)]\\ A(i)f(0)+B(i)&=1+f(0)(P+\sum_{j=3}^{k_1+k_2+k_3}p_jA(i+j))+\sum_{j}p_jB(i+j)\\ &\begin{cases} A(i)=P+\sum_{j=3}^{k_1+k_2+k_3}p_jA(i+j)\quad 可以递推求\\ B(i)=1+\sum_{j=3}^{k_1+k_2+k_3}p_jB(i+j)\\ \end{cases} \end{aligned}
A(i)f(0)+B(i)A(i)f(0)+B(i)=1+Pf(0)+j=3∑k1+k2+k3pj[A(i+j)f(0)+B(i+j)]=1+f(0)(P+j=3∑k1+k2+k3pjA(i+j))+j∑pjB(i+j){A(i)=P+∑j=3k1+k2+k3pjA(i+j)可以递推求B(i)=1+∑j=3k1+k2+k3pjB(i+j)
再把方程
f
(
0
)
=
1
+
P
f
(
0
)
+
∑
j
=
3
k
1
+
k
2
+
k
3
p
j
f
(
j
)
f(0)=1+Pf(0)+\sum_{j=3}^{k_1+k_2+k_3}p_jf(j)
f(0)=1+Pf(0)+∑j=3k1+k2+k3pjf(j)考虑进去,有
f
(
0
)
=
1
+
P
f
(
0
)
+
∑
j
=
3
k
1
+
k
2
+
k
3
p
j
[
A
(
j
)
f
(
0
)
+
B
(
j
)
]
f
(
0
)
=
1
+
∑
j
=
3
k
1
+
k
2
+
k
3
p
j
B
(
j
)
+
(
P
+
∑
j
=
3
k
1
+
k
2
+
k
3
p
j
A
(
j
)
)
f
(
0
)
f
(
0
)
=
B
(
0
)
+
A
(
0
)
f
(
0
)
\begin{aligned} f(0)&=1+Pf(0)+\sum_{j=3}^{k_1+k_2+k_3}p_j[A(j)f(0)+B(j)]\\ f(0)&=1+\sum_{j=3}^{k_1+k_2+k_3}p_jB(j)+(P+\sum_{j=3}^{k_1+k_2+k_3}p_jA(j))f(0)\\ f(0)&=B(0)+A(0)f(0) \end{aligned}
f(0)f(0)f(0)=1+Pf(0)+j=3∑k1+k2+k3pj[A(j)f(0)+B(j)]=1+j=3∑k1+k2+k3pjB(j)+(P+j=3∑k1+k2+k3pjA(j))f(0)=B(0)+A(0)f(0)
其实会发现
f
(
0
)
f(0)
f(0)也满足通项公式。
注意: 在算 p j p_j pj时排除 a , b , c a,b,c a,b,c的情况。
#include"cstdlib"
#include"cstdio"
#include"cstring"
#include"cmath"
#include"queue"
#include"algorithm"
#include"iostream"
#define eps 1e-12
using namespace std;
int main()
{
int t;
cin>>t;
while(t--)
{
int n,k[4],a,b,c;
int i,j,l;
scanf("%d%d%d%d%d%d%d",&n,&k[1],&k[2],&k[3],&a,&b,&c);
double p[22];
memset(p,0,sizeof(p));
for(i=1;i<=k[1];i++) for(j=1;j<=k[2];j++) for(l=1;l<=k[3];l++) p[i+j+l]+=1.0/(k[1]*k[2]*k[3]); //求出掷出k点的概率
p[a+b+c]-=1.0/(k[1]*k[2]*k[3]); //单独考虑下分别a,b,c点的情况
p[0]=1.0/(k[1]*k[2]*k[3]);
double A[600],B[600];
memset(A,0,sizeof(A));
memset(B,0,sizeof(B));
for(i=n;i>=0;i--) //递推求解
{
A[i]=p[0];
B[i]=1;
if(i==n) continue;
for(j=1;j<=k[1]+k[2]+k[3];j++)
{
A[i]+=p[j]*A[i+j];
B[i]+=p[j]*B[i+j];
}
}
printf("%.15f\n",B[0]/(1-A[0]));
}
return 0;
}