CF913F Strongly Connected Tournament
Description
这是一个在All-Right城的国际象棋比赛。$n$个运动员被邀请参加比赛,比赛依照以下规则举办:
- 期初,每个运动员与其他每一个运动员比赛,他们之间没有任何关系。
- 在比赛之后,组织者造了一副有向的完全图,这张图把每名运动员看做点,对于每对运动员他们之间有一条边:他们之间比赛的胜利者是这条边的起点,输了的人是终点。
- 然后对原图进行缩点,之后这张图变成了由原图的强连通分量组成的一条链$A_1\rightarrow A_2\rightarrow A_3\rightarrow \cdots \rightarrow A_k$
- 之后对将强联通分量$A_1$里的点放到$|A_1|$里面,将强联通分量$A_2$中的所有点放入$|A_2|$里面,以此类推
- 为了确定每个运动员在各自强联通分量中的排名,需要再在每个强联通分量中将不断地进行1-5这五个步骤,也就是说,$A_i$中的$k$个人都需要和其他的$k-1$个人再比赛一次。
- 如果一个强联通分量里只有一个人,那么他已经没有对手了,那么他的水平就已经确定了,就可以不用继续进行了。
运动员们被标号为$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; }