首页 > 其他 > 详细

【题解】担心

时间:2020-02-15 16:06:58      阅读:70      评论:0      收藏:0      [点我收藏+]

区间DP + 组合计数

\(f(i, j)\)为只考虑\([i, j]\)段,且\(i,j\)能够相遇的概率。

特别地,设\(f(0, i)\)\(i\)能打败左边所有人的概率,\(f(i, n+1)\)\(i\)能打败右边所有人的概率。

转移只需要枚举中间点\(k\),考虑最后剩下三个人\((i, k, j)\),有一半概率抽到\((i, k)\),一半概率抽到\((k, j)\),计算概率即可。a

关键在于在到达最终状态\((i, k, j)\)之前,要保证\((i, k)\)\((k, j)\)不能被选中对决,因此要计算概率并乘上去。

\(k-i+1=n, j-k+1=m\),则能达到最终状态的概率为:
\[ \dfrac{(n-1)!(m-1)! \binom{n+m-4}{n-2}}{\dfrac{(n+m-2)!}{2}} \]
其中\((n-1)!\)\(n-1\)\(n-2\)的排列

\(\dfrac{(n+m-2)!}{2}\)\((n+m-2)\)\(n+m-4\)的排列(总方案数)

即先内部排列,最后再整体可重排列。

对于\(f(0, i)\)\(f(i, n+1)\)类似。

Code

#include <cstdio>
#include <algorithm>
using namespace std;

#define File(s) freopen(s".in", "r", stdin), freopen(s".out", "w", stdout)

const int p = 998244353, N = 505, inv2 = 499122177;
inline int add(int x, int y){return x+y>=p ? x+y-p : x+y;}
inline int sub(int x, int y){return x-y<0 ? x-y+p :x-y;}
inline int mul(int x, int y){return 1LL * x * y % p;}
inline int power(int x, int y){
    int res = 1;
    for(; y; y>>=1, x = mul(x, x)) if(y & 1) res = mul(res, x);
    return res;
}

int fac[N], ifac[N];
void preBinom(int n){
    fac[0] = fac[1] = 1;
    for(int i=2; i<=n; i++) fac[i] = mul(fac[i-1], i);
    ifac[n] = power(fac[n], p - 2);
    for(int i=n-1; i>=0; i--) ifac[i] = mul(ifac[i+1], i+1);
}
int C(int n, int m){return mul(fac[n], mul(ifac[m], ifac[n-m]));}
int F(int n, int m){ // 左右两边分别为n,m个元素
    return mul(mul(mul(fac[n-1], fac[m-1]), C(n+m-4, n-2)), mul(ifac[n+m-2], 2));
}

int a[N];
int Pr[N][N], f[N][N];

int main(){
    int n, pos;
    scanf("%d%d", &n, &pos);
    preBinom(n+3);
    for(int i=1; i<=n; i++) scanf("%d", a + i), f[i-1][i] = 1;
    f[n][n+1] = 1;
    for(int i=1; i<=n; i++)
        for(int j=i+1; j<=n; j++){
            Pr[i][j] = mul(a[i] % p, power((a[i] + a[j]) % p, p - 2));
            Pr[j][i] = sub(1, Pr[i][j]);
        }
    for(int len=2; len<=n; len++){
        for(int i=1; i<len; i++) f[0][len] = add(f[0][len], 
            mul(
                mul(mul(f[0][i], f[i][len]), Pr[len][i]),
                mul(mul(mul(fac[i-1], fac[len-i]), C(len-2, i-1)), ifac[len-1])
            )
        );
        int now = n + 1 - len;
        for(int i=n+2-len; i<=n; i++){
            f[n+1-len][n+1] = add(f[n+1-len][n+1],
                mul(
                    mul(mul(f[n+1-len][i], f[i][n+1]), Pr[n+1-len][i]),
                    mul(mul(mul(fac[i-now], fac[n-i]), C(n-1-now, i-now-1)), ifac[n-now])
                )
            );
        }
        for(int i=1; i+len<=n; i++){
            int j = i + len;
            for(int k=i+1; k<j; k++)
                f[i][j] = add(f[i][j],
                    mul(mul(
                        mul(inv2, add(Pr[i][k], Pr[j][k])),
                        mul(f[i][k], f[k][j])),
                        F(k-i+1, j-k+1)
                    )
                );
        }
    }
    printf("%d\n", mul(f[0][pos], f[pos][n+1]));
    return 0;
}

【题解】担心

原文:https://www.cnblogs.com/RiverHamster/p/sol-oj4043.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!