溫馨鏈接
校內OJ 3548,請手動前往
題目重述
遊戲每輪雙方輪流投擲一枚硬幣,率先投出正面者獲勝,當前輸者成為下一輪的先手。
求出首輪先手在第 n n n 場獲勝的概率。
題解
設 g [ 1 ] g[1] g[1] 爲一局遊戲中,先手贏的概率; g [ 0 ] g[0] g[0] 反之。
先手贏的概率相當於後手輸的概率,反之亦然。
假設先手在第一次投擲時獲勝,概率爲 1 2 = 1 2 1 \displaystyle\frac12=\frac1{2^1} 21=211;
若在第一次後手失敗後先手第二次投擲時獲勝,概率爲 1 2 ⋅ 1 2 ⋅ 1 2 = 1 2 3 \displaystyle\frac12\cdot\frac12\cdot\frac12=\frac1{2^3} 21⋅21⋅21=231。
可知遊戲持續到先手在其第 i i i 次投擲時勝利的概率爲 1 2 2 i + 1 \displaystyle\frac1{2^{2i+1}} 22i+11。
以此類推,可以推廣到極限
∞
\infin
∞。故有
g
[
1
]
=
∑
i
=
0
∞
1
2
2
i
+
1
=
1
2
(
1
−
1
4
∞
)
1
−
1
4
=
2
3
g[1]=\sum_{i=0}^{\infin} \frac1{2^{2i+1}}=\frac{\displaystyle \frac12\left(1-\frac1{4^\infin}\right)}{\displaystyle1-\frac14}=\frac23
g[1]=i=0∑∞22i+11=1−4121(1−4∞1)=32
設
f
[
i
,
1
]
f[i,1]
f[i,1] 表示第
i
i
i 局勝利的概率;
f
[
i
,
0
]
f[i,0]
f[i,0] 反之。顯然有遞推式
f
[
n
,
1
]
=
f
[
n
−
1
,
0
]
⋅
g
[
1
]
+
f
[
n
−
1
,
1
]
⋅
g
[
0
]
f
[
n
,
0
]
=
f
[
n
−
1
,
0
]
⋅
g
[
0
]
+
f
[
n
−
1
,
1
]
⋅
g
[
1
]
f[n,1]=f[n-1,0]\cdot g[1]+f[n-1,1]\cdot g[0]\\ f[n,0]=f[n-1,0]\cdot g[0]+f[n-1,1]\cdot g[1]
f[n,1]=f[n−1,0]⋅g[1]+f[n−1,1]⋅g[0]f[n,0]=f[n−1,0]⋅g[0]+f[n−1,1]⋅g[1]
其意義為當前先手勝利概率為前一局勝利概率乘上作為本局後手勝利概率加上相反情況的概率,當前先手失敗的概率與此同理。
將
f
[
i
,
1
]
+
f
[
i
,
0
]
=
1
f[i,1]+f[i,0]=1
f[i,1]+f[i,0]=1,
g
[
1
]
+
g
[
0
]
=
1
g[1]+g[0]=1
g[1]+g[0]=1,
p
=
g
[
1
]
p=g[1]
p=g[1] 代入遞推式,則首輪先手在第
i
i
i 局遊戲中獲勝的概率
x
i
=
x
i
−
1
(
1
−
p
)
+
(
1
−
x
i
−
1
)
p
=
−
1
3
x
i
−
1
+
2
3
x_i=x_{i-1}(1-p)+(1-x_{i-1})~p=-\frac13x_{i-1}+\frac23
xi=xi−1(1−p)+(1−xi−1) p=−31xi−1+32
運用待定係數法構造,得
x
i
−
1
2
=
−
1
3
(
x
i
−
1
−
1
2
)
x_i-\frac12=-\frac13\left(x_{i-1}-\frac12\right)
xi−21=−31(xi−1−21)
顯然,
{
x
n
}
\lbrace x_n\rbrace
{xn} 爲公比爲
−
1
3
\displaystyle-\frac13
−31 的等比數列,通項公式
x
n
=
−
1
3
n
−
1
⋅
(
x
1
−
1
2
)
+
1
2
x_n=-\frac1{3^{n-1}}\cdot(x_1-\frac12)+\frac12
xn=−3n−11⋅(x1−21)+21
又
x
1
=
g
[
1
]
=
2
3
x_1=g[1]=\displaystyle\frac23
x1=g[1]=32,則
x
n
=
(
−
1
)
n
−
1
⋅
1
2
(
1
3
n
+
1
)
x_n=(-1)^{n-1}\cdot\frac12\left(\frac1{3^n}+1\right)
xn=(−1)n−1⋅21(3n1+1)
寫作代碼即 (g[n & 1] * power(inv3, n) + 1 + P) * inv2 % P
,其中 g[]
為
{
−
1
,
1
}
\{-1, 1\}
{−1,1}。
#include <iostream>
using namespace std;
const long long g[] = {-1, 1};
constexpr long long P = 998244353;
constexpr long long inv2 = (P + 1) >> 1, inv3 = (P + 1) / 3;
template <typename T>
T power(T a, T b){
T s = 1;
for (; b; b >>= 1, a = a * a % P)
if (b & 1) s = s * a % P;
return s;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
long long n; cin >> n;
cout << (g[n & 1] * power(inv3, n) + 1 + P) * inv2 % P << endl;
return 0;
}
感谢观看,作者蒟蒻,如有错误敬请指教。
2019.11.11 结尾撒花