2019.11.11 投擲硬幣

溫馨鏈接

校內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} 212121=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=022i+11=14121(141)=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[n1,0]g[1]+f[n1,1]g[0]f[n,0]=f[n1,0]g[0]+f[n1,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=xi1(1p)+(1xi1) p=31xi1+32
運用待定係數法構造,得
x i − 1 2 = − 1 3 ( x i − 1 − 1 2 ) x_i-\frac12=-\frac13\left(x_{i-1}-\frac12\right) xi21=31(xi121)
顯然, { 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=3n11(x121)+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)n121(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 结尾撒花

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值