• CF913F Strongly Connected Tournament


    Description

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

    1. 期初,每个运动员与其他每一个运动员比赛,他们之间没有任何关系。
    2. 在比赛之后,组织者造了一副有向的完全图,这张图把每名运动员看做点,对于每对运动员他们之间有一条边:他们之间比赛的胜利者是这条边的起点,输了的人是终点。
    3. 然后对原图进行缩点,之后这张图变成了由原图的强连通分量组成的一条链$A_1 ightarrow A_2 ightarrow A_3 ightarrow cdots ightarrow 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+ inom{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
    ",g[n]);
        return 0;
    }
    Strongly Connected Tournament
  • 相关阅读:
    C# DataTable的詳細用法 .
    webgl复习笔记——纹理装配
    webgl复习笔记——图形装配过程
    webgl复习笔记——三角形平移、旋转(2)
    webgl复习笔记——[回顾]从零绘制三角形
    webgl复习笔记——三角形平移、旋转(1)
    webgl复习笔记——绘制三角形、四边形
    webgl复习笔记——通过arraybuffer绘制多个点
    webgl复习笔记——可以自由设置颜色的点
    webgl复习笔记——绘制 点、多个点
  • 原文地址:https://www.cnblogs.com/JDFZ-ZZ/p/13450194.html
Copyright © 2020-2023  润新知