[ARC165E] Random Isolation

Problem Statement

There is a tree with N vertices numbered 1 to N. The i-th edge connects vertices Ai and Bi.

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 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 PQ, we have Q0(mod998244353). Thus, there is a unique integer R such that R×QP(mod998244353),0R<998244353. Report this R.

Constraints

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

考虑一个大小为 n,与其相邻的有 m 个点的连通块,在某一时刻操作出来的概率是 (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 @   灰鲭鲨  阅读(34)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示