码迷,mamicode.com
首页 > 其他好文 > 详细

CF913F Strongly Connected Tournament

时间:2020-01-13 23:46:03      阅读:94      评论:0      收藏:0      [点我收藏+]

标签:getc   href   需要   cto   stp   mod   复杂度   include   i++   

题面

题解

\(f(n)\) 表示 \(n\) 个人比赛总场数的期望值,通过枚举拓补序最后的强连通分量可得:
\[ f(n) = \sum_{i = 1}^n s(i)c(n, i)\left[f(i) + f(n - i) + i(n - i) + \frac{i(i - 1)}2 \right] \]
其中 \(s(n)\) 表示 \(n\) 个点能够形成强连通分量的概率,\(c(n, i)\) 表示 \(n\) 个点中有 \(i\) 个点被剩下 \(n - i\) 个点打败的概率。

这样就可以很好地理解后面那一堆东西:\(f(i)\)\(f(n - i)\) 表示内部分别解决的场次,\(i(n - i)\) 是比出那 \(i\) 个最菜的人需要的场次,\(\dfrac {i(i-1)}2\)\(i\) 个人形成强连通分量需要的场次。

由于 \(c(n, n) = 1\),所以上式中的 \(f(n)\) 可以解出来,为:
\[ f(n) = \frac 1{1 - s(n)}\left\{\sum_{i=1}^{n - 1} s(i)c(n - i)\left[f(i) + f(n - i) + i(n - i) + \frac {i(i - 1)}2 \right] \right\} \]
接下来考虑如何求 \(c(n, i)\)

边界条件 \(c(n, 0) = 1\),通过讨论 \(n\) 是否被吊打可以得出:
\[ c(n, i) = (1 - p)^ic(n - 1, i) + p^{n - i}c(n - 1, i - 1) \]
\(s(n)\) 同样比较好求,同样枚举拓补序最后一个强连通分量得:
\[ s(n) = 1 - \sum_{i = 1}^{n - 1} s(i)c(n, i) \]
于是问题解决,时间复杂度 \(\Theta(n^2)\)

代码

#include <cstdio>
#include <algorithm>
#include <vector>

inline int read()
{
    int data = 0, w = 1; char ch = getchar();
    while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
    if (ch == '-') w = -1, ch = getchar();
    while (ch >= '0' && ch <= '9') data = data * 10 + (ch ^ 48), ch = getchar();
    return data * w;
}

const int N(2010), Mod(998244353);
int n, a, b, p[N], q[N], c[N][N], f[N], s[N];
inline int C(int x) { return 1ll * x * (x - 1) / 2 % Mod; }
int fastpow(int x, int y)
{
    int ans = 1;
    for (; y; y >>= 1, x = 1ll * x * x % Mod)
        if (y & 1) ans = 1ll * ans * x % Mod;
    return ans;
}

int main()
{
    p[0] = q[0] = 1;
    n = read(), a = read(), b = read(), a = 1ll * a * fastpow(b, Mod - 2) % Mod;
    for (int i = 1; i <= n; i++) p[i] = 1ll * p[i - 1] * a % Mod;
    a = Mod + 1 - a;
    for (int i = 1; i <= n; i++) q[i] = 1ll * q[i - 1] * a % Mod;
    for (int i = 0; i <= n; i++) c[i][0] = 1;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= i; j++)
            c[i][j] = (1ll * q[j] * c[i - 1][j] + 1ll * p[i - j] * c[i - 1][j - 1]) % Mod;
    for (int i = 1; i <= n; i++) s[i] = 1;
    for (int i = 2; i <= n; i++) for (int j = 1; j < i; j++)
        s[i] = (s[i] - 1ll * s[j] * c[i][j] % Mod + Mod) % Mod;
    for (int i = 2; i <= n; i++)
    {
        f[i] = 1ll * s[i] * C(i) % Mod;
        for (int j = 1; j < i; j++)
            f[i] = (f[i] + 1ll * s[j] * c[i][j] % Mod * ((f[j] + f[i - j]) % Mod + (1ll * j * (i - j) % Mod + C(j)) % Mod) % Mod) % Mod;
        f[i] = 1ll * f[i] * fastpow(Mod + 1 - s[i], Mod - 2) % Mod;
    }
    printf("%d\n", f[n]);
    return 0;
}

CF913F Strongly Connected Tournament

标签:getc   href   需要   cto   stp   mod   复杂度   include   i++   

原文地址:https://www.cnblogs.com/cj-xxz/p/12189690.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!