【CTS2019】氪金手游(动态规划)

【CTS2019】氪金手游(动态规划)

题面

LOJ
洛谷

题解

首先不难发现整个图构成的结构是一棵树,如果这个东西是一个外向树的话,那么我们在意的只有这棵子树内的顺序关系,子树外的关系与这棵子树之间的限制无关。所以我们只需要强制根节点在其他儿子之前的就行了(你可以认为如果这次随机抽到了子树外面的东西就重新抽一次,这个概率等于只考虑子树权值和的概率),那么这里的概率就是\(\frac{w_u}{\sum w}\)。然后每个根节点显然可以独立考虑,所以只需要把所有根节点的结果直接乘起来就好了。
那么对于\(w\)也有概率的情况,设\(f[i][w]\)表示以\(i\)为根的子树中,权值和为\(w\)时根节点合法的概率。
这个随便转移一下就很好做了。
现在加上了反向边,反向边强制了儿子要在根节点之前出现,而状态也只要两种,要么反向边在前要么反向边在后,那么设\(f[i][w][j]\)表示以\(i\)为子树,子树和为\(w\),至少有\(j\)条反向边不满足条件的概率,既然强制了若干个不反向,那么就是你枚举一些边,然后强制把它变成正向边,剩下的反向边直接删掉,这样子就可以求出这个概率。
注意到这个容斥的系数就是简单的\(\pm 1\),所以只需要直接把容斥系数带进去算就行了。
这样子复杂度可以做到\(O(n^2)\)

#include<iostream>
#include<cstdio>
using namespace std;
#define MOD 998244353
#define MAX 1010
inline int read()
{
	int x=0;bool t=false;char ch=getchar();
	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
	if(ch=='-')t=true,ch=getchar();
	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
	return t?-x:x;
}
int fpow(int a,int b){int s=1;while(b){if(b&1)s=1ll*s*a%MOD;a=1ll*a*a%MOD;b>>=1;}return s;}
struct Line{int v,next;}e[MAX<<1];
int h[MAX],cnt=1;
inline void Add(int u,int v){e[cnt]=(Line){v,h[u]};h[u]=cnt++;}
int f[MAX][3*MAX],sz[MAX],p[MAX][4],inv[MAX*3],tmp[MAX*3],n,ans;
void dfs(int u,int ff)
{
	sz[u]=1;
	for(int i=h[u];i;i=e[i].next)
	{
		int v=e[i].v;if(v==ff)continue;
		dfs(v,u);
		for(int j=0;j<=3*sz[u];++j)
			for(int k=0;k<=3*sz[v];++k)
			{
				int val=1ll*f[u][j]*f[v][k]%MOD;
				if(i&1)tmp[j+k]=(tmp[j+k]+val)%MOD;
				else tmp[j+k]=(tmp[j+k]+MOD-val)%MOD,tmp[j]=(tmp[j]+val)%MOD;
			}
		sz[u]+=sz[v];for(int j=0;j<=3*sz[u];++j)f[u][j]=tmp[j],tmp[j]=0;
	}
	for(int j=0;j<=sz[u]*3;++j)f[u][j]=1ll*f[u][j]*inv[j]%MOD;
}
int main()
{
	n=read();
	for(int i=1;i<=n;++i)
	{
		int a1=read(),a2=read(),a3=read();
		int inv=fpow(a1+a2+a3,MOD-2);
		f[i][1]=1ll*a1*inv%MOD;
		f[i][2]=2ll*a2*inv%MOD;
		f[i][3]=3ll*a3*inv%MOD;
	}
	for(int i=1;i<n;++i)
	{
		int u=read(),v=read();
		Add(u,v);Add(v,u);
	}
	inv[0]=inv[1]=1;for(int i=2;i<=3*n;++i)inv[i]=1ll*inv[MOD%i]*(MOD-MOD/i)%MOD;
	dfs(1,0);for(int i=0;i<=3*n;++i)ans=(ans+f[1][i])%MOD;
	printf("%d\n",ans);
	return 0;
}
posted @ 2019-05-23 21:06  小蒟蒻yyb  阅读(598)  评论(0编辑  收藏  举报