CF913F Strongly Connected Tournament

Description

这是一个在All-Right城的国际象棋比赛。$n$个运动员被邀请参加比赛,比赛依照以下规则举办:

  1. 期初,每个运动员与其他每一个运动员比赛,他们之间没有任何关系。
  2. 在比赛之后,组织者造了一副有向的完全图,这张图把每名运动员看做点,对于每对运动员他们之间有一条边:他们之间比赛的胜利者是这条边的起点,输了的人是终点。
  3. 然后对原图进行缩点,之后这张图变成了由原图的强连通分量组成的一条链$A_1\rightarrow A_2\rightarrow A_3\rightarrow \cdots \rightarrow A_k$
  4. 之后对将强联通分量$A_1$里的点放到$|A_1|$里面,将强联通分量$A_2$中的所有点放入$|A_2|$里面,以此类推
  5. 为了确定每个运动员在各自强联通分量中的排名,需要再在每个强联通分量中将不断地进行1-5这五个步骤,也就是说,$A_i$中的$k$个人都需要和其他的$k-1$个人再比赛一次。
  6. 如果一个强联通分量里只有一个人,那么他已经没有对手了,那么他的水平就已经确定了,就可以不用继续进行了。

运动员们被标号为$1$到$n$,标号被用在最初的图上。我们知道运动员$i$能赢运动员$j$的概率为$p$$(i<j)$。

你需要去帮助组织比赛,求出比赛总场数的期望值。

答案显然可以表示成$\frac PQ$,$P$,$Q$为互质的整数。且$Q$不等于$0$。 输出$P$乘上$Q$相对于$998244353$的逆元。

简而言之答案对$998244353$取模。

Solution

设$f_i$为一个大小为$i$的点集打完一轮之前相互连通,打完之后相互连通的概率,$g_i$为一个有$i$个点的已知胜负状态的$SCC$期望打多少场会结束游戏,$h_i$为一个有$i$个点的已知胜负状态的竞赛图期望打多少场会结束游戏,$dp_{i,j}$为大小为$i$的点集中经过比赛有$j$个点被其他所有点打败

那么:

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

$$f_i=1- \sum_{j=1}^{i-1} dp_{i,j}f_j$$

$$g_i=f_ig_i+ \binom{i}{2} + \sum_{j=1}^{i-1}dp_{i,j}f_j(g_j + h_{i-j})$$

$$h_i=f_ig_i + \sum_{j=1}^{i-1}dp_{i,j}f_j(g_j + h_{i-j})$$

算就完事了,答案为$g_n$

#include<iostream>
#include<cstdio>
using namespace std;
long long n,a,b,p,q,pp[2005],pq[2005],dp[2005][2005],f[2005],g[2005],h[2005];
const long long mod=998244353;
inline long long read()
{
    long long f=1,w=0;
    char ch=0;
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')
        {
            f=-1;
        }
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        w=(w<<1)+(w<<3)+ch-'0';
        ch=getchar();
    }
    return f*w;
}
long long ksm(long long a,long long P)
{
    long long ret=1;
    while(P)
    {
        if(P&1)
        {
            (ret*=a)%=mod;
        }
        (a*=a)%=mod;
        P>>=1;
    }
    return ret;
}
int main()
{
    n=read();
    a=read();
    b=read();
    p=a*ksm(b,mod-2)%mod;
    q=(1-p+mod)%mod;
    pp[0]=pq[0]=1ll;
    for(long long i=1;i<=n;i++)
    {
        pp[i]=pp[i-1]*p%mod;
        pq[i]=pq[i-1]*q%mod;
    }
    dp[0][0]=1ll;
    for(long long i=1;i<=n;i++)
    {
        for(long long j=0;j<=i;j++)
        {
            (dp[i][j]+=dp[i-1][j]*pp[j]%mod)%=mod;
            if(j)
            {
                (dp[i][j]+=dp[i-1][j-1]*pq[i-j]%mod)%=mod;
            }
        }
    }
    for(long long i=1;i<=n;i++)
    {
        f[i]=1ll;
        for(long long j=1;j<i;j++)
        {
            ((f[i]-=dp[i][j]*f[j]%mod)+=mod)%=mod;
        }
    }
    for(long long i=1;i<=n;i++)
    {
        for(long long j=1;j<i;j++)
        {
            long long temp=dp[i][j]*f[j]%mod*((g[j]+h[i-j])%mod)%mod;
            (g[i]+=temp)%=mod;
            (h[i]+=temp)%=mod;
        }
        (g[i]+=i*(i-1)%mod*ksm(2,mod-2)%mod);
        (g[i]*=ksm((1-f[i]+mod)%mod,mod-2))%=mod;
        (h[i]+=f[i]*g[i]%mod)%=mod;
    }
    printf("%lld\n",g[n]);
    return 0;
}
Strongly Connected Tournament

 

posted @ 2020-08-07 07:25  QDK_Storm  阅读(216)  评论(0编辑  收藏  举报