题解 CF913F【Strongly Connected Tournament】

$\text{Link}$

$\text{update 2022.2.21}$:修正一处笔误。

题意

给你 $n$ 个点,其中对于所有的 $i,j(i<j)$连有一条的有向边,其中有 $p=\dfrac a b$ 的概率为 $i$ 连向 $j$。

对这张完全图缩点,并对于每个强连通分量重复执行以上操作直至只剩一个点。

求期望的连边数,对 $998244353$ 取模。

$n\le 2000$。

思路

nb dp 题。

我们设 $dp_i$ 表示 $i$ 个点时的期望答案。

考虑枚举最弱的强联通分量的大小,则对于这个强联通分量里的点已经构成了一张完全图,并且其它的点都打赢过这个强联通分量里的点。换句话说,如果这个强联通分量大小为 $j$,则已经连了 $j(i-j)+\dfrac{j(j-1)}2$ 条边了。

考虑需要算出 $i$ 个点组成强联通图的概率与 $i$ 个点都打赢了其中 $j$ 个点的概率,不妨分别设其为 $c_i,d_{i,j}$。

考虑一次转移,还需要在强联通分量内部和外部递归处理,列出转移方程:

$$dp_i=\sum_{j=1}^ic_jd_{i,j}\left(j(i-j)+\dfrac {j(j-1)}2+dp_j+dp_{i-j}\right)$$

但是我们发现当 $i=j$ 即这个图自己构成一个强联通分量时,$dp_i$ 会转移到自己,考虑变个形:

$$dp_i=\dfrac{\sum_{j=1}^{i-1}\left[c_jd_{i,j}\left(j(i-j)+\dfrac {j(j-1)}2+dp_j+dp_{i-j}\right)\right]+c_id_{i,i}\dfrac {i(i-1)}2}{1-c_id_{i,i}}$$

现在需要算出 $c$ 和 $d$。

考虑只要图中没有点被其它点都吊打的情况它就是强联通图,$c$ 的转移十分简单:

$$c_i=1-\sum_{j=1}^{i-1}c_jd_{i,j}$$

对于 $d$,考虑新加入一个点,如果它是输的那 $j$ 个中的一个,则它要输给 $i-j$ 个点,否则它要赢 $j$ 个点。转移也比较简单(注意边的方向与编号大小的关系):

$$d_{i,j}=(1-p)^jd_{i-1,j}+p^{i-j}d_{i-1,j-1}$$

时间复杂度 $\Theta(n^2)$。

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
namespace IO{//by cyffff

}
const int N=2000+10,mod=998244353;
inline int qpow(int x,int y){
    int res=1;
    while(y){
        if(y&1) res=1ll*res*x%mod;
        x=1ll*x*x%mod;
        y>>=1;
    }
    return res;
} 
int n,p,c[N],d[N][N],dp[N];
int main(){
    n=read();
    int a=read(),b=read();
    p=1ll*a*qpow(b,mod-2)%mod;
    d[1][0]=d[1][1]=1;
    for(int i=2;i<=n;i++){
        d[i][0]=1;
        for(int j=1;j<=i;j++)
            d[i][j]=(1ll*d[i-1][j]*qpow(mod+1-p,j)+1ll*d[i-1][j-1]*qpow(p,i-j))%mod;
    }
    for(int i=1;i<=n;i++){
        int res=0;
        for(int j=1;j<i;j++)
            res=(res+1ll*c[j]*d[i][j])%mod;
        c[i]=((1-res)%mod+mod)%mod;
    }
    for(int i=1;i<=n;i++){
        int res=0;
        for(int j=1;j<i;j++){
            int tmp=(dp[j]+dp[i-j])%mod;
            tmp=(tmp+1ll*j*(i-j))%mod;
            tmp=(tmp+1ll*j*(j-1)/2)%mod;
            res=(res+1ll*c[j]*d[i][j]%mod*tmp)%mod;
        }
        res=(res+1ll*c[i]*d[i][i]%mod*(i*(i-1)/2))%mod;
        dp[i]=1ll*res*qpow(mod+1-1ll*c[i]*d[i][i]%mod,mod-2)%mod;
    }
    write(dp[n]);
    flush();
}

再见 qwq~

posted @ 2021-11-22 18:28  ffffyc  阅读(24)  评论(0)    收藏  举报  来源