CF913F Strongly Connected Tournament 容斥+dp

123 篇文章 0 订阅
28 篇文章 0 订阅

Description


n<=2000个人参加比赛

  1. 两两比一场,比完连个图,边i->j表示i赢了j
  2. 连完那个图强联通分量缩起来,强连通分量内继续比,即强连通分量递归进行1、2,直到每个强连通分量大小为1
  3. i<j时i有a/b的概率赢j,问每个人比赛的场数的总和的期望,答案%998244353。

n ≤ 2000 n\le2000 n2000

Solution


考虑设f[n]表示n个点的答案,一个套路就是枚举哪些点打成了一个强连通分量。设g[i]表示i个点打成一个强连通分量的概率,h[i,j]表示i个点里面j个点和剩余(i-j)个点打全输的概率,那么
f [ i ] = ∑ j = 1 i g [ j ] h [ i , j ] ( f [ i − j ] + f [ j ] + ( j 2 ) + ( i − j ) j ) f[i]=\sum_{j=1}^{i}{g[j]h[i,j]\left(f[i-j]+f[j]+\binom{j}{2}+\left(i-j\right)j\right)} f[i]=j=1ig[j]h[i,j](f[ij]+f[j]+(2j)+(ij)j)
好像挺显然的吧。。
然后考虑g和h怎么求,g可以用1减去不合法的概率,那么就是 g [ i ] = 1 − ∑ j = 1 i − 1 g [ j ] ∗ h [ i , j ] g[i]=1-\sum_{j=1}^{i-1}{g[j]*h[i,j]} g[i]=1j=1i1g[j]h[i,j]
一个图不强连通的话我们枚举一个出度为0的连通分量,然后让其余的边都指向它就行了

再看看h怎么求,我们可以讨论一下第i个人放在两个集合中的哪一个,于是就有 h [ i , j ] = h [ i − 1 , j ] ⋅ ( 1 − p ) j + h [ i − 1 , j − 1 ] ⋅ p i − j h[i,j]=h[i-1,j]\cdot{(1-p)}^j+h[i-1,j-1]\cdot{p^{i-j}} h[i,j]=h[i1,j](1p)j+h[i1,j1]pij
这里相当于我们默认i个中j个的编号比较大。。

然后我们发现f会转移到自己,那么移项解一个方程就完事了

Code


#include <stdio.h>
#include <string.h>
#include <algorithm>
#define rep(i,st,ed) for (LL i=st;i<=ed;++i)

typedef long long LL;
const int MOD=998244353;
const int ny2=(MOD+2)/2;
const int N=2005;

LL f[N],g[N],h[N][N];

LL ksm(LL x,LL dep) {
	LL res=1; x=(x%MOD+MOD)%MOD;
	for (;dep;dep>>=1) {
		(dep&1)?(res=res*x%MOD):0;
		x=x*x%MOD;
	}
	return res;
}

int main(void) {
	int n,a,b; scanf("%d%d%d",&n,&a,&b);
	LL p=a*ksm(b,MOD-2)%MOD;
	h[1][0]=h[1][1]=1;
	rep(i,2,n) {
		h[i][0]=1;
		rep(j,1,i) {
			h[i][j]=(h[i-1][j]*ksm(1+MOD-p,j)%MOD+h[i-1][j-1]*ksm(p,i-j)%MOD)%MOD;
		}
	}
	g[1]=1;
	rep(i,2,n) {
		rep(j,1,i-1) g[i]=(g[i]+g[j]*h[i][j]%MOD)%MOD;
		g[i]=(MOD+1-g[i])%MOD;
	}
	f[1]=0;
	rep(i,2,n) {
		f[i]=g[i]*h[i][i]%MOD*i%MOD*(i-1)%MOD*ny2%MOD;
		rep(j,1,i-1) {
			f[i]=(f[i]+(j*(j-1)%MOD*ny2%MOD+(i-j)*j%MOD+f[j]+f[i-j])%MOD*g[j]%MOD*h[i][j]%MOD)%MOD;
		}
		f[i]=f[i]*ksm(1-g[i]*h[i][i]%MOD,MOD-2)%MOD;
	}
	printf("%lld\n", f[n]);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值