ABC333F Bomb Game 2 题解

2023-12-29 16:47:18

原题链接
洛谷链接

题意

n n n 个人排成一排,从前往后编号为 1 ~ n 1 \sim n 1n。接下来不断进行以下操作,直到剩下一个人:

  • 1 2 \frac{1}{2} 21? 的概率把排头一炮崩了。
  • 1 2 \frac{1}{2} 21? 的概率使排头站到队尾。

问:对于每个 1 ≤ i ≤ n 1 \leq i \leq n 1in,编号为 i i i 的人存活下来的概率是多少?

答案对 998244353 998244353 998244353 取模。

题解

这是一道肥肠煎蛋(但我没做出来)的 DP。

首先,我们设 f [ i ] [ j ] f[i][j] f[i][j] 表示剩下 i i i 个人,从前到后第 j j j 个人的存活概率。显然,当 i = 1 i=1 i=1 时的存货概率为 100 % 100\% 100%。因此初始状态为:

f [ 1 ] [ 1 ] = 1 f[1][1]=1 f[1][1]=1

i ≥ 2 i \geq 2 i2 时, f [ i ] [ j ] f[i][j] f[i][j] 由两部分组成:

第一部分:

第一个人可能被崩了。此时人数减 1 1 1,而第 j j j 个人的位置向左移了一位,因此 j j j 也减 1 1 1。此时的存活概率为:

f [ i ? 1 ] [ j ? 1 ] f[i-1][j-1] f[i?1][j?1]

第二部分:

第一个人可能回到了队尾。此时人数不变,而第 j j j 个人位置左移一位,所以 j j j 1 1 1。此时的存货概率为:

f [ i ] [ j ? 1 ] f[i][j-1] f[i][j?1]

又因为达成这两种情况的概率都是 1 2 \frac{1}{2} 21?,所以我们得出状态转移方程:

f [ i ] [ j ] = 1 2 ( f [ i ? 1 ] [ j ? 1 ] + f [ i ] [ j ? 1 ] ) f[i][j]=\frac{1}{2}(f[i-1][j-1]+f[i][j-1]) f[i][j]=21?(f[i?1][j?1]+f[i][j?1])

但是!你以为这样就可以了吗?

读者:不然呢?

别忘了,当第一个人结束操作,他并不是左移一位,而是回到队尾!因此:

f [ i ] [ j ] = 1 2 ( f [ i ? 1 ] [ i ] + f [ i ] [ i ] ) f[i][j]=\frac{1}{2}(f[i-1][i]+f[i][i]) f[i][j]=21?(f[i?1][i]+f[i][i])

此时,顺序形成了一个环,不满足 DP 无后效性的原则。

那真的没办法了吗?

不!

发现形成环的部分的 i i i 都相同,所以我们尝试将 f [ i ] [ 1 ] , f [ i ] [ 2 ] , … , f [ i ] [ i ] f[i][1],f[i][2],\dots,f[i][i] f[i][1],f[i][2],,f[i][i] f [ i ] [ 1 ] f[i][1] f[i][1] f [ i ? 1 ] [ 1 … i ] f[i-1][1\dots i] f[i?1][1i] 表示出来:

f [ i ] [ 1 ] = f [ i ] [ 1 ] f[i][1]=f[i][1] f[i][1]=f[i][1]

f [ i ] [ 2 ] = 1 2 ( f [ i ? 1 ] [ 1 ] + f [ i ] [ 1 ] ) = 1 2 f [ i ? 1 ] [ 1 ] + 1 2 f [ i ] [ 1 ] f[i][2]=\frac{1}{2}(f[i-1][1]+f[i][1])=\frac{1}{2}f[i-1][1]+\frac{1}{2}f[i][1] f[i][2]=21?(f[i?1][1]+f[i][1])=21?f[i?1][1]+21?f[i][1]

f [ i ] [ 3 ] = 1 2 ( 1 2 ( f [ i ? 1 ] [ 1 ] + f [ i ] [ 1 ] ) + f [ i ? 1 ] [ 2 ] ) = 1 2 f [ i ? 1 ] [ 2 ] + 1 4 f [ i ? 1 ] [ 1 ] + 1 4 f [ i ] [ 1 ] f[i][3]=\frac{1}{2}(\frac{1}{2}(f[i-1][1]+f[i][1])+f[i-1][2])=\frac{1}{2}f[i-1][2]+\frac{1}{4}f[i-1][1]+\frac{1}{4}f[i][1] f[i][3]=21?(21?(f[i?1][1]+f[i][1])+f[i?1][2])=21?f[i?1][2]+41?f[i?1][1]+41?f[i][1]

f [ i ] [ 4 ] = … f[i][4]=\dots f[i][4]=

最后得出 f [ i ] [ i ] = 1 2 f [ i ? 1 ] [ i ? 1 ] + 1 4 f [ i ? 1 ] [ i ? 2 ] + ? + 1 2 i ? 1 f [ i ? 1 ] [ 1 ] + 1 2 i ? 1 f [ i ] [ 1 ] f[i][i]=\frac{1}{2}f[i-1][i-1]+\frac{1}{4}f[i-1][i-2]+\dots+\frac{1}{2^{i-1}}f[i-1][1]+\frac{1}{2^{i-1}}f[i][1] f[i][i]=21?f[i?1][i?1]+41?f[i?1][i?2]+?+2i?11?f[i?1][1]+2i?11?f[i][1]。又因 f [ i ] [ 1 ] = 1 2 ( f [ i ] [ i ] + f [ i ? 1 ] [ i ] ) f[i][1]=\frac{1}{2}(f[i][i]+f[i-1][i]) f[i][1]=21?(f[i][i]+f[i?1][i]),所以:

f [ i ] [ 1 ] = ∑ k = 1 i 1 2 i ? k + 1 f [ i ? 1 ] [ k ] + 1 2 i f [ i ] [ 1 ] f[i][1]=\sum_{k=1}^i \frac{1}{2^{i-k+1}}f[i-1][k]+\frac{1}{2^i}f[i][1] f[i][1]=k=1i?2i?k+11?f[i?1][k]+2i1?f[i][1]

解一下方程,得到:

f [ i ] [ 1 ] = 2 i 2 i ? 1 ( ∑ k = 1 i 1 2 i ? k + 1 f [ i ? 1 ] [ k ] ) f[i][1]=\frac{2^i}{2^i-1}(\sum_{k=1}^i \frac{1}{2^{i-k+1}}f[i-1][k]) f[i][1]=2i?12i?(k=1i?2i?k+11?f[i?1][k])

这样,我们直接算出了 f [ i ] [ 1 ] f[i][1] f[i][1],这样后面的值就可以直接用状态转移方程了。而 f [ n ] [ 1 … n ] f[n][1\dots n] f[n][1n] 即为所求。

总结以下式子:

  • 初始值: f [ 1 ] [ 1 ] = 1 f[1][1]=1 f[1][1]=1
  • 状态转移方程:
    f [ i ] [ j ] = { 2 i 2 i ? 1 ( ∑ k = 1 i 1 2 i ? k + 1 f [ i ? 1 ] [ k ] ) j = 1 1 2 ( f [ i ? 1 ] [ j ? 1 ] + f [ i ] [ j ? 1 ] ) 2 ≤ j ≤ i f[i][j]= \left\{\begin{matrix} \frac{2^i}{2^i-1}(\sum_{k=1}^i \frac{1}{2^{i-k+1}}f[i-1][k]) & j=1\\\\ \frac{1}{2}(f[i-1][j-1]+f[i][j-1]) & 2 \leq j \leq i \end{matrix}\right. f[i][j]=? ? ??2i?12i?(k=1i?2i?k+11?f[i?1][k])21?(f[i?1][j?1]+f[i][j?1])?j=12ji?
  • 答案: f [ n ] [ 1 … n ] f[n][1\dots n] f[n][1n]

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=3005,mod=998244353;
int n;
long long f[N][N],p,pw[N],inv[N];
long long power(long long x,int y){
    long long res=1;
    for(;y;y>>=1){
        if(y&1)res=res*x%mod;
        x=x*x%mod;
    }
    return res;
}
int main(){
    pw[0]=inv[0]=1,p=power(2,mod-2);
    cin>>n;
    for(int i=1;i<=n;++i)pw[i]=pw[i-1]*2%mod,inv[i]=inv[i-1]*p%mod;
    f[1][1]=1;
    for(int i=2;i<=n;++i){
        for(int j=1;j<=i;++j)f[i][1]=(f[i][1]+f[i-1][j]*inv[i-j+1]%mod)%mod;
        f[i][1]=f[i][1]*pw[i]%mod*power(pw[i]-1,mod-2)%mod;
        for(int j=2;j<=i;++j)f[i][j]=(f[i][j-1]+f[i-1][j-1])*p%mod;
    }
    for(int i=1;i<=n;++i)cout<<f[n][i]<<' ';
    return 0;
}

文章来源:https://blog.csdn.net/BasketballChick/article/details/135275106
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。