zoukankan      html  css  js  c++  java
  • CF913F Strongly Connected Tournament

    题面

    题解

    (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 ight] ]

    其中 (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{frac{n(n-1)s(i)}2 + sum_{i=1}^{n - 1} s(i)c(n - i)left[f(i) + f(n - i) + i(n - i) + frac {i(i - 1)}2 ight] ight} ]

    接下来考虑如何求 (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
    ", f[n]);
    	return 0;
    }
    
  • 相关阅读:
    程序员的四个阶段
    2010Year Plans
    HttpHandler HttpModule入门篇
    Lucene.net索引文件的并发访问和线程安全性
    stream流写到MemoryStream内存流引发得问题
    ASP.NET 2.0 多文件上传小经验
    HTML 迷魂灯
    如何在Windows下搭建Android开发环境
    利用Lucene.net搭建站内搜索(4)数据检索
    数据加密和解密
  • 原文地址:https://www.cnblogs.com/cj-xxz/p/12189690.html
Copyright © 2011-2022 走看看