[ARC165E] Random Isolation

Problem Statement

There is a tree with $N$ vertices numbered $1$ to $N$. The $i$-th edge connects vertices $A_i$ and $B_i$.

Let us keep performing the following operation until each connected component of the graph has $K$ or fewer vertices.

  • From the $N$ vertices, choose one uniformly at random that belongs to a connected component with $K+1$ or more vertices. Delete all edges with the chosen vertex as an endpoint.

Find the expected value of the number of times the operation is performed, modulo $998244353$.

How to print an expected value modulo $\text{mod }{998244353}$

It can be proved that the sought expected value is always a rational number. Additionally, under the constraints of this problem, it can also be proved that when that value is represented as an irreducible fraction $\frac{P}{Q}$, we have $Q \not \equiv 0 \pmod{998244353}$. Thus, there is a unique integer $R$ such that $R \times Q \equiv P \pmod{998244353}, 0 \leq R < 998244353$. Report this $R$.

Constraints

  • $1 \leq K < N \leq 100$
  • $1 \leq A_i,B_i \leq N$
  • The given graph is a tree.
  • All input values are integers.
期望题首先有个经典转换:消掉连通块大于等于 $K$ 的限制,然后当我选到了一个小于 $K$ 的点就不管继续选,这样子答案是不会变的。

考虑一个大小为 \(n\),与其相邻的有 \(m\) 个点的连通块,在某一时刻操作出来的概率是 \(\frac{(n+m)!}{n!m!}\),而这些概率之和就是期望。

用树形 dp 求出来一共有多少个大小为 \(n\),与其相连的点有 \(m\) 个的连通块,分别计算即可。

#include<bits/stdc++.h>
using namespace std;
const int P=998244353,N=105;
int n,k,u,v,sz[N],in[N],jc[N],iv[N],inv[N],dp[N][N][N],hd[N],ans,e_num,f[N][N];
struct edge{
	int v,nxt;
}e[N<<1];
void dfs(int x,int y)
{
	dp[x][sz[x]=1][(bool)y]=1;
	for(int v=hd[x];v;v=e[v].nxt)
	{
		if(e[v].v==y)
			continue;
		dfs(e[v].v,x);
		for(int i=0;i<=sz[x];i++)
			for(int j=0;j<=sz[x]+1;j++)
				f[i][j]=dp[x][i][j],dp[x][i][j]=0;
		for(int i=sz[x];~i;i--)
		{
			for(int j=sz[x];~j;j--)
			{
				for(int a=sz[e[v].v];a;a--)
					for(int b=sz[e[v].v];b;b--)
						(dp[x][i+a][j+b-1]+=f[i][j]*1LL*dp[e[v].v][a][b]%P)%=P;
				(dp[x][i][j+1]+=f[i][j])%=P;
			}
		}
		sz[x]+=sz[e[v].v];
	}
	for(int i=k+1;i<=sz[x];i++)
		for(int j=0;j<=sz[x];j++)
			(ans+=jc[i]*1LL*jc[j]%P*iv[i+j]%P*dp[x][i][j]%P)%=P;
	/*for(int i=0;i<=sz[x];i++)
		for(int j=0;j<=sz[x];j++)
			if(dp[x][i][j])
				printf("%d %d %d %d\n",x,i,j,dp[x][i][j]);*/
}
void add_edge(int u,int v)
{
	in[u]++;
	e[++e_num]=(edge){v,hd[u]};
	hd[u]=e_num;
}
int main()
{
	scanf("%d%d",&n,&k);
	jc[0]=jc[1]=iv[0]=iv[1]=inv[1]=1;
	for(int i=2;i<N;i++)
	{
		jc[i]=1LL*jc[i-1]*i%P;
		inv[i]=1LL*(P-P/i)*inv[P%i]%P;
		iv[i]=1LL*iv[i-1]*inv[i]%P;
	}
	for(int i=1;i<n;i++)
		scanf("%d%d",&u,&v),add_edge(u,v),add_edge(v,u);
	dfs(1,0);
	printf("%d",ans);
}
posted @ 2023-09-22 20:06  灰鲭鲨  阅读(46)  评论(0)    收藏  举报