首页 > 其他分享 >Atcoder Grand Contest 058 F - Authentic Tree DP

Atcoder Grand Contest 058 F - Authentic Tree DP

时间:2023-08-07 16:55:11浏览次数:31  
标签:Atcoder Contest int siz Tree ec 边点 MAXN hd

考虑给 \(f(T)\) 赋予组合意义。一个直观的想法是,在每条边中间新建一个节点,然后每次选择一条边对应的点,然后把它删掉,递归剩余的两个部分,但是你会发现这样分母不对,应该是 \(n\) 但在这个模型里只有 \(n-1\)。

考虑魔改这个模型。我们在每个边对应的点下面添加 \(998244352\) 个点,你发现这样总点数 \(\bmod 998244353\) 就等于 \(n\)。于是 \(f(T)\) 实际上就是这样一个东西:

设得到的数中有 \(k\) 个节点,那么考虑将 \(1\sim k\) 随机填入这棵树的 \(k\) 个节点中,有多大概率满足每条边所对应的点小于它所有的邻居。

考虑容斥,即我们钦定一些边点大于它的父亲,容斥系数为 \((-1)^{\text{钦定的边点个数}}\),这样考虑从每个边点向其所有儿子连边,对于那些钦定的边点,从其父亲向这个边点本身连边,那这种情况的概率就是 \(\prod\dfrac{1}{siz_i}\)。这样就可以树上背包了,设 \(dp_{i,j}\) 表示考虑 \(i\) 子树中的点,目前以 \(i\) 为根的部分的 \(siz\equiv j\pmod{998244353}\) 的概率乘以容斥系数之和。转移见代码。时间复杂度 \(O(n^2)\)。

const int MAXN=5000;
const int MOD=998244353;
int n,hd[MAXN+5],to[MAXN*2+5],nxt[MAXN*2+5],ec;
void adde(int u,int v){to[++ec]=v;nxt[ec]=hd[u];hd[u]=ec;}
int dp[MAXN+5][MAXN+5],siz[MAXN+5],res,inv[MAXN+5];
void dfs(int x,int f){
	dp[x][siz[x]=1]=1;
	for(int e=hd[x];e;e=nxt[e]){
		int y=to[e];if(y==f)continue;dfs(y,x);
		static int tmp[MAXN+5];memset(tmp,0,sizeof(tmp));
		int sum=0;
		for(int i=1;i<=siz[y];i++)sum=(sum+1ll*inv[i]*inv[i]%MOD*dp[y][i])%MOD;
		for(int i=1;i<=siz[x];i++)for(int j=1;j<=siz[y];j++)
			tmp[i+j]=(tmp[i+j]+1ll*dp[x][i]*dp[y][j]%MOD*inv[j]%MOD*inv[j])%MOD;
		siz[x]+=siz[y];
		for(int i=1;i<=siz[x];i++)dp[x][i]=(1ll*sum*dp[x][i]-tmp[i]+MOD)%MOD;
	}
}
int main(){
	scanf("%d",&n);
	for(int i=(inv[0]=inv[1]=1)+1;i<=n;i++)inv[i]=1ll*inv[MOD%i]*(MOD-MOD/i)%MOD;
	for(int i=1,u,v;i<n;i++)scanf("%d%d",&u,&v),adde(u,v),adde(v,u);
	dfs(1,0);for(int i=1;i<=n;i++)res=(res+1ll*dp[1][i]*inv[i])%MOD;
	printf("%d\n",res);
	return 0;
}

标签:Atcoder,Contest,int,siz,Tree,ec,边点,MAXN,hd
From: https://www.cnblogs.com/tzcwk/p/agc058F.html

相关文章

  • Atcoder ABC313_C-Approximate Equalization 2
    AT_ABC313_C-ApproximateEqualization2Description:给定一个整数序列\(A=(A_1,A_2,···,A_n)\),可以做以下操作任意次(可能为0):选择一个整数对\((i,j)\)\((1\leqi,j\leqn)\),使得\(A[i]-\)=\(1\),\(A[j]+\)=\(1\),求出使得数列\(A\)中的\(max-min\leq1\)所需的最少......
  • 在AMD PetaLinux中添加命令pstree
    命令pstree将相关进程以树状图显示,方便查看进程间的关系。由于调试需要,需要在Linux里使用命令pstree。但是PetaLinux产生的Linux映像,默认不带命令pstree。在rootfs里查找pstree首先使用命令“petalinux-config-crootfs”尝试在rootfs里查找pstree。没有找到pstree。在psmisc......
  • Atcoder Beginner Contest 313
    CDEF有\(n(1\len\le40)\)张牌,每一张牌正面写上了数字\(a_i\),背面写上了数字\(b_i\)。最初所有牌都是正面朝上。有\(m\)个机器,每个机器有参数\(x_i,y_i(1\lex_i,y_i\len)\),\(x_i\)可以等于\(y_i\)。每个机器只能启动一次,并且有\(\frac{1}{2}\)的概率将牌\(......
  • AtCoder Beginner Contest 313
    A-ToBeSaikyo#include<bits/stdc++.h>usingnamespacestd;intmain(){ ios::sync_with_stdio(0),cin.tie(0); intn; cin>>n; vector<int>a(n); for(auto&i:a)cin>>i; cout<<max(0,*max_element(a.beg......
  • [国家集训队] Tree II 题解报告
    [国家集训队]TreeII一道·真·板子·题就是练习LCT懒标记的题目除了翻转标记以外还要维护乘法标记和加法标记注意加法标记和乘法标记的维护!!!加法标记因为splay的区间大小不是固定的,所以我们要维护size,并且子树的sum要加上size乘上标记其他的就只用直接加上即可voidpusha......
  • 「解题报告」AtCoder Beginner Contest 313
    比赛地址:AtCoderBeginnerContest313-AtCoder后记:请正确理解题意后再做题!!!A-ToBeSaikyoA-ToBeSaikyo(atcoder.jp)每个人有一个数值,问第一个人要加多少才能使得自己的数值变成最大的。就这么个破题我还WA了一发//Thecodewaswrittenbyyifan,andyifanis......
  • vim 文件树插件 nerdtree
    安装"在.vimrc中加入Plug'scrooloose/nerdtree'"nerdtree插件Plug'ryanoasis/vim-devicons'"nerdtree的文件图标----推荐下载配置letg:NERDTreeDirArrowExpandable='ʃ'"展开目录图标letg:NERDTreeDirArrowCollapsibl......
  • AtCoder Beginner Contest (ABC) 313 D-E
    Tasks-AtCoderBeginnerContest313PS:当时看到D过的比E多就一直在考虑D,但还没做出来,其实个人感觉E比D简单。 D-OddorEven交互题。有n个数,最多可以询问n次然后要求判断出这n个数的奇偶性。每次可以询问数组里任意k个元素的和是不是奇数一开始想到的是高斯消元,n次总能......
  • vue 开源项目 安装脚手架报错问题 ERESOLVE unable to resolve dependency tree
       在安装项目依赖时,很大可能会遇到安装不成功的问题,其中有一个很大的原因,可能就是因为你的npm版本导致的 使用--force或--legacy-peer-deps可解决这种情况。--force会无视冲突,并强制获取远端npm库资源,当有资源冲突时覆盖掉原先的版本。--legacy-peer-deps标志是在v7......
  • AtCoder Beginner Contest 313 A-E Code
    比赛链接:AtCoderBeginnerContest313-AtCoder A:#include<bits/stdc++.h>usingnamespacestd;intmain(){cin.tie(0);ios::sync_with_stdio(false);intn;cin>>n;intp1;cin>>p1;intma......