ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

#22 CF913F

2022-05-30 15:31:48  阅读:150  来源: 互联网

标签:连通 22 cdot int read CF913F dp MOD


Strongly Connected Tournament

题目描述

点此看题

解法

设 \(g[i]\) 表示 \(i\) 个点的竞赛图,解决它的比赛总场数期望值。转移考虑一次定向后取出入度为 \(0\) 的那个强连通块,设这个强连通块大小为 \(j\),就可以得到子问题 \(g[j]\) 和 \(g[i-j]\)

那么如何规划那个入度为 \(0\) 的强连通块?可以拆分成两部分,第一部分是块内和其他点的连边,我们要求块内的点单向连接其他点,但是注意概率是和编号大小关系有关的,所以我们要用 \(dp\) 计算;第二部分是块内自身的连边,需要能形成强连通块。显然这两部分连边带来的概率也是独立的,并且其他连边我们可以一概不考察。

第一部分:按照编号顺序从小到大规划,设 \(dp[i][j]\) 表示考虑前 \(i\) 个点,钦定 \(j\) 个点单向连接其他点的概率:

\[dp[i][j]=dp[i-1][j-1]\cdot (1-p)^{i-j}+dp[i-1][j]\cdot p^j \]

第二部分:设 \(f[i]\) 表示 \(i\) 个点形成强连通分量的概率,转移正难则反法,减去形成更小强联通块的情况:

\[f[i]=1-\sum_{j=1}^{i-1}dp[i][j]\cdot f[j] \]

现在我们知道形成大小为 \(j\) 的强连通块的概率是 \(dp[i][j]\cdot f[j]\),利用这个也可以写出 \(g\) 的转移:

\[g[i]=\sum_{j=1}^{i}dp[i][j]\cdot f[j]\cdot (\frac{j(j-1)}{2}+j(i-j)+g[j]+g[i-j]) \]

但是注意到两边都有 \(g[i]\),所以简单地移项就可以得到最终的转移:

\[g[i]=\frac{dp[i][i]\cdot f[i]\cdot\frac{i(i-1)}{2}+\sum_{j=1}^{i-1}dp[i][j]\cdot f[j]\cdot (\frac{j(j-1)}{2}+j(i-j)+g[j]+g[i-j])}{1-dp[i][i]\cdot f[i]} \]

时间复杂度 \(O(n^2)\)

#include <cstdio>
#include <iostream>
using namespace std;
const int M = 2005;
const int MOD = 998244353;
#define int long long
int read()
{
	int x=0,f=1;char c;
	while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
	while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
	return x*f;
}
int n,a,b,p,p1[M],p2[M],dp[M][M],f[M],g[M];
int qkpow(int a,int b)
{
	int r=1;
	while(b>0)
	{
		if(b&1) r=r*a%MOD;
		a=a*a%MOD;
		b>>=1;
	}
	return r;
}
signed main()
{
	n=read();a=read();b=read();
	p=a*qkpow(b,MOD-2)%MOD;p1[0]=p2[0]=1;
	for(int i=1;i<=n;i++)
	{
		p1[i]=p1[i-1]*p%MOD;
		p2[i]=p2[i-1]*(MOD+1-p)%MOD;
	}
	dp[0][0]=1;
	for(int i=1;i<=n;i++)
	{
		dp[i][0]=1;
		for(int j=1;j<=i;j++)
			dp[i][j]=(dp[i-1][j-1]*p2[i-j]+
			dp[i-1][j]*p1[j])%MOD;
	}
	for(int i=1;i<=n;i++)
	{
		f[i]=1;
		for(int j=1;j<i;j++)
			f[i]=(f[i]+MOD-dp[i][j]*f[j]%MOD)%MOD;
	}
	for(int i=1;i<=n;i++)
	{
		int s=dp[i][i]*f[i]%MOD,r=i*(i-1)/2*s%MOD;
		for(int j=1;j<i;j++)
		{
			int t=j*(i-j)+j*(j-1)/2+g[j]+g[i-j];
			r=(r+t%MOD*dp[i][j]%MOD*f[j])%MOD;
		}
		g[i]=r*qkpow(MOD+1-s,MOD-2)%MOD;
	}
	printf("%lld\n",g[n]);
}

标签:连通,22,cdot,int,read,CF913F,dp,MOD
来源: https://www.cnblogs.com/C202044zxy/p/16326908.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有