首页 > 其他分享 >CF1060F Shrinking Tree

CF1060F Shrinking Tree

时间:2023-02-17 21:24:35浏览次数:50  
标签:int ti Tree op using CF1060F Shrinking dp define

题面传送门

考虑枚举最后剩下的点,然后令它为根。

对于每个不是根的点,我们记 \(ti_i\) 表示 \(i\) 是什么时候和它的父亲合并的,\(op_i\) 表示 \(i\) 在和父亲合并的时候是不是和一号点合并的。

我们考虑对 \(ti\) 和 \(op\) 两个数组计数,最后除以 \(2^{n-1}(n-1)!\) 就是最后剩下这个点的概率。

\(ti\) 显然如果是一个排列就合法,关键是 \(op\) 。观察发现,如果一个点 \(x\) 的祖先合并的时间均早于 \(x\),那么 \(op_x=1\) ,反之 \(op_x=0\)。对于每个 \(op_x=0\),都会使排列的答案乘上 \(2\)。

考虑设 \(dp_{i,j}\) 表示 \(i\) 子树内的答案已经确定,要求祖先的删除时间不能早于当前子树内第 \(j\)个 的方案数。特别的,如果 \(j\) 大于 \(i\) 子树大小,则对祖先的时间没有限制。

考虑合并这两个类似背包的东西。枚举限制最终在什么位置,就可以用组合数计数,单次dp复杂度\(O(n^3)\)。

然后考虑加上当前节点,当前节点显然要小于限制的位置。然后先钦定这个点的 \(op_x=0\),然后减去 \(op_x=1\) 的方案数,就可以做到当 \(op_x=0\) 的时候对排列数乘 \(2\) 了。

总时间复杂度 \(O(n^4)\),当然可以前缀和优化到 \(O(n^3)\),但是我懒。

#include<bits/stdc++.h>
#define Gc() getchar() 
#define Me(x,y) memset(x,y,sizeof(x))
#define Mc(x,y) memcpy(x,y,sizeof(x))
#define d(x,y) ((m)*(x-1)+(y))
#define R(n) (rnd()%(n)+1)
#define Pc(x) putchar(x)
#define LB lower_bound
#define UB upper_bound
#define PB push_back
using ll=long long;using db=double;using lb=long db;using ui=unsigned;using ull=unsigned ll;
using namespace std;const int N=50+5,M=5e6+5,K=5e4,mod=998244353,Mod=mod-1;const db eps=1e-9;const int INF=1e9+7;mt19937 rnd(263082);
int n,m,k,x,y,z,Si[N];vector<int> S[N];lb dp[N][N],g[N],C[N][N];
void DP(int x,int La){
 	dp[x][1]=1;Si[x]=0;for(int i:S[x]) if(i^La){
		DP(i,x);Mc(g,dp[x]);Me(dp[x],0);
		for(int j=1;j<=Si[x]+1;j++){
			for(int h=1;h<=Si[i]+1;h++){
				if(j==Si[x]+1&&h==Si[i]+1){ dp[x][Si[x]+Si[i]+1]+=g[j]*dp[i][h]*C[Si[x]+Si[i]][Si[i]];continue;}
				if(j<=Si[x]) for(int p=j;p<=j+h-1;p++) dp[x][p]+=g[j]*dp[i][h]*C[p-1][j-1]*C[Si[x]+Si[i]-p][Si[x]-j];
				if(h<=Si[i]) for(int p=h;p<=j+h-1;p++) dp[x][p]+=g[j]*dp[i][h]*C[p-1][h-1]*C[Si[x]+Si[i]-p][Si[i]-h];
			}
		}
		Si[x]+=Si[i];
	}
	if(La){
		Mc(g,dp[x]);Me(dp[x],0);
		for(int i=1;i<=Si[x]+1;i++) for(int j=1;j<=i;j++) dp[x][i+1]+=g[i]*2,dp[x][j]-=g[i];
		Si[x]++;
	}
}
int main(){
	freopen("1.in","r",stdin);
	int i,j;scanf("%d",&n);for(i=1;i<n;i++) scanf("%d%d",&x,&y),S[x].PB(y),S[y].PB(x);
	for(i=0;i<=n;i++) for(C[i][0]=j=1;j<=i;j++) C[i][j]=C[i-1][j]+C[i-1][j-1];
	for(i=1;i<=n;i++){
		Me(dp,0),DP(i,0);
		lb Ans=0;for(j=1;j<=n;j++) Ans+=dp[i][j];
		for(j=1;j<n;j++) Ans/=2*j;printf("%.10Lf\n",Ans);
	} 
}

标签:int,ti,Tree,op,using,CF1060F,Shrinking,dp,define
From: https://www.cnblogs.com/275307894a/p/17131511.html

相关文章

  • 3、TreeMap源码解析
    目录1TreeMap基本介绍2红黑树数据结构回顾3成员变量4内部类Entry5构造函数6重要方法分析6.1get方法分析6.2put方法分析6.3插入调整函数fixAfterInsertion()解析6.......
  • element-ui的tree结构自定义节点点击是否可触发展开缩放
    近期公司项目,用element-ui的tree结构渲染一套数据,层级以两级或三级居多其中一级节点无实际意义,因此希望一级节点点击后正常展开缩放二级节点有实际意义,点击后,若下方有三......
  • 【CF207C3】Game with Two Trees
    【CF207C3】GamewithTwoTreesDescription有两颗动态加入点的树,每条边有一个字符每次加入完点后T1中到根的链在T2中的匹配次数之和Input一行一个数\(q\)Output输......
  • 208. Implement Trie (Prefix Tree)[Medium]
    208.ImplementTrie(PrefixTree)Atrie(pronouncedas"try")orprefixtreeisatreedatastructureusedtoefficientlystoreandretrievekeysinadataset......
  • TreeMap实现排序
    TreeMapTreeMap实现SortMap接口,能够把它保存的记录根据键排序,默认是按键值的升序排序,也可以指定排序的比较器。当用Iterator遍历TreeMap时,得到的记录是排过序的。TreeMap取......
  • TreeMap是按照key的字典顺序来排序
    一、TreeMapTreeMap默认排序规则:按照key的字典顺序来排序(升序)字典排序(lexicographicalorder)是一种对于随机变量形成序列的排序方法。即按照字母顺序,或者数字小大顺序,由小......
  • QTreewidget勾选功能
    //connect(ui->treeWidget,&QTreeWidget::itemClicked,this,&PushSelectUser::treeItemChanged); voidPushSelectUser::treeItemChanged(QTreeWidgetItem*item,intcol......
  • zTree实现树形结构菜单
    文章目录​​一、简介​​​​二、前端渲染效果​​​​三、实现步骤​​​​1、数据库表结构​​​​2、引入zTree插件​​​​3、树形结构实体类SysModule​​​​4、表示......
  • Git命令列表--git-worktree
    GitWorktree名称git-worktree-管理附加到同一存储库的多个工作树。语法gitworktreeadd[-f][--detach][--checkout][--lock[--reason<string>]][-b<new-br......
  • Codeforces Round #851 (Div. 2)-F. XOR, Tree, and Queries-树、异或、并查集
    题目:https://codeforces.com/contest/1788/problem/F题解:(首先他和线性基没什么瓜系)想这个问题大概可以分成几个部分:1、很自然地考虑记\(p_x\)表示从根节点走到x路径......