CF913F Strongly Connected Tournament

Link
(f_i)表示(n)个点的期望场次。
(C_{i,j})表示从(i)个点中选(j)个点,这(j)个点被其它(i-j)个点打败的概率。
(S_i)表示(i)个点直接形成scc的概率。
先求(C_{i,j}),边界为(C_{i,0}=1),考虑枚举第(i)个点在哪个集合,得到(C_{i,j}=p^{i-j}C_{i-1,j-1}+(1-p)^jC_{i-1,j})
然后求(S_i),考虑补集容斥计算不能直接形成scc的概率,枚举拓扑序最大的scc的大小,得到(S_i=1-sumlimits_{j=1}^{i-1}S_jC_{i,j})
再考虑求(f_i),边界为(f_0=0),依旧考虑枚举拓扑序最大的scc的大小,得到(f_i=sumlimits_{j=1}^iS_jC_{i,j}(f_j+f_{i-j}+j(i-j)+{jchoose 2}))
注意到(f_i)会转移到自己,所以在枚举到(j=i)我们先计算(S_iC_{i,i}{ichoose 2}),最后再乘上(frac1{1-S_iC_{i,i}})即可。

#include<cstdio>
const int N=2007,P=998244353;
int f[N],C[N][N],S[N],p[N],q[N];
int inc(int a,int b){return a+=b-P,a+(a>>31&P);}
int dec(int a,int b){return a-=b,a+(a>>31&P);}
int mul(int a,int b){return 1ll*a*b%P;}
int pow(int a,int k){int r=1;for(;k;k>>=1,a=mul(a,a))if(k&1)r=mul(a,r);return r;}
int main()
{
    int n,a,b;scanf("%d%d%d",&n,&a,&b),p[0]=q[0]=1,p[1]=mul(a,pow(b,P-2)),q[1]=dec(1,p[1]);
    for(int i=2;i<=n;++i) p[i]=mul(p[i-1],p[1]),q[i]=mul(q[i-1],q[1]);
    for(int i=0;i<=n;++i) for(int j=C[i][0]=1;j<=i;++j) C[i][j]=inc(mul(p[i-j],C[i-1][j-1]),mul(q[j],C[i-1][j]));
    for(int i=1;i<=n;++i) for(int j=S[i]=1;j<i;++j) S[i]=dec(S[i],mul(S[j],C[i][j]));
    for(int i=1;i<=n;++i)
    {
	f[i]=mul(mul(S[i],C[i][i]),i*(i-1)/2);
	for(int j=1;j<i;++j) f[i]=inc(f[i],mul(mul(S[j],C[i][j]),j*(i-j)+j*(j-1)/2+f[j]+f[i-j]));
	f[i]=mul(f[i],pow(dec(1,mul(C[i][i],S[i])),P-2));
    }
    printf("%d",f[n]);
}
原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/12705959.html