首页 > 其他分享 >[ARC087F] Squirrel Migration 题解

[ARC087F] Squirrel Migration 题解

时间:2022-11-03 18:22:52浏览次数:68  
标签:Squirrel fiz 题解 ll times siz include ARC087F 个点

[ARC087F] Squirrel Migration

给你一个 \(n\) 个节点的树,求一个 \(1\sim n\) 的排列\((p_1,p_2,\dots p_n)\),使得 \(\sum dist(i,p_i)\) 最大。

求这样的排列个数。答案对 \(10^9+7\) 取模。

相当于对于每个点 \(i\),找到一个 \(p_i\) 与之匹配(但是 \(p_i\) 可以去匹配别的点)(说废话)。

结论:所有点 \(i\) 与 \(p_i\) 在这颗树的重心的不同子树中(或者其中一个点是重心本身)。

证明:

  1. 一定存在一种构造使得 \(i\) 和 \(p_i\) 存在于不同的重心子树中。将以重心为根的每个点按照 dfs 序组成一个环,因为重心的任意一颗子树大小小于 $ \frac{n}{2}$,且这颗子树内的点在环上连续,所以一个点左侧第 \(\frac{n}{2}\) 个点一定不在这颗点所属子树内。
  2. 满足这一条件的构造中存在一种可以取到最大答案。考虑反证,假如存在一个点 \(i\) 和 \(p_i\) 在同一子树内,那么可以根据第一条,一定存在另一个点 \(j\) 和 \(p_j\) 在同一子树内,我们将 \(i\to p_j,j\to p_i\) 一定会比现在更优。证明这点只需要对 \(i\) 和 \(p_i\),\(j\) 和 \(p_j\) 取 \(lca\),更改后的路径长度即比原先多 \(2\) 倍的 \(lca\) 间的路径长度。

现在我们就是要求有多少种方案使得 \(i\) 与 \(p_i\) 在重心的不同子树中,这个并不好直接求,使用容斥。

定义 \(f_i\) 为排列中有 \(i\) 个点不合法的方案数,剩下的点任意匹配的方案数,答案即为:

\[ans=\sum_{i=0}^{n}(-1)^i\times f_i\times (n-i)! \]

现在考虑如何求 \(f\)。从子树合并的角度考虑。

假设子树的大小为 \(x\),其中有 \(k\) 个点满足 \(i\) 与 \(p_i\) 在同一子树中,那么其方案数为 \(\binom{x}{k}^2k!\)。意义是从中找出 \(k\) 个点,和 \(k\) 个与之匹配的点(所以平方),然后这 \(k\) 个点可以任意排列。

于是可以使用树形背包合并每个子树的答案。转移是朴素的。

\[f_i\gets \sum_{j=0}^{i} f_{i-j}\times \binom{siz_u}{j}^2\times j! \]

具体的转移细节和实现见代码。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <cmath>

using namespace std;
typedef long long ll;
typedef pair<int,int>ttfa;
inline ll read(){
	ll x=0,f=1;char ch=getchar();
	while(ch<'0'||'9'<ch){if(ch=='-')f=-1;ch=getchar();}
	while('0'<=ch&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
	return x*f;
}
const int N=100005;
const ll MOD=1000000007;
int n,root,siz[N],fiz[N];
ll fac[N],ifc[N],dp[N],ans;
inline ll C(ll n,ll r){return fac[n]*ifc[r]%MOD*ifc[n-r]%MOD;}
vector<int>edge[N];
inline ll fpr(ll b,ll t=MOD-2,ll x=1){
	for(;t;t>>=1,b=b*b%MOD)
		if(t&1)x=x*b%MOD;
	return x;
}
void dfs(int u,int f){
	siz[u]=1,fiz[u]=0;
	for(auto v:edge[u]){
		if(v==f)continue;
		dfs(v,u);
		siz[u]+=siz[v];
		fiz[u]=max(fiz[u],siz[v]);
	}fiz[u]=max(fiz[u],n-siz[u]);
	if(fiz[u]<fiz[root])root=u;
}
int main(){
	n=read();
	fac[0]=ifc[0]=1;
	for(int i=1;i<=n;++i)fac[i]=fac[i-1]*i%MOD;
	ifc[n]=fpr(fac[n]);
	for(int i=n-1;i>=1;--i)ifc[i]=ifc[i+1]*(i+1)%MOD;
	for(int i=1;i<n;++i){
		int u=read(),v=read();
		edge[u].push_back(v);
		edge[v].push_back(u);
	}
	fiz[root=0]=n;dfs(1,0);dfs(root,0);
	dp[0]=1ll;
	for(auto v:edge[root]){
		int s=siz[v];
		for(int i=n;i>=0;--i){//背包
			for(int j=1;j<=min(i,s);++j){
				ll tmp=C(s,j)*C(s,j)%MOD*fac[j]%MOD;
				dp[i]=(dp[i]+dp[i-j]*tmp%MOD)%MOD;
			}
		}
	}
	for(int i=0;i<=n;++i)
		ans=(ans+((i&1)?-1ll:1ll)*dp[i]*fac[n-i]%MOD+MOD)%MOD;
	printf("%lld\n",ans);
	return 0;
}

标签:Squirrel,fiz,题解,ll,times,siz,include,ARC087F,个点
From: https://www.cnblogs.com/BigSmall-En/p/16855411.html

相关文章

  • 【题解】P8818 [CSP-S 2022] 策略游戏
    【题解】P8818[CSP-S2022]策略游戏这道题应该是CSP-S2022所有题里面最简单的一道了,主要是有点套路,刨开套路,其实就是个静态维护区间最大最小值的板子。作为一名场外......
  • [题解] HDU7060 Separated Number 思路整理
    题目链接HDU7060SeparatedNumber题目大意给一个\(n\)位数,把该数字分成\(k\)段,每种方案的贡献为其分割出的段的数字之和。求所有分法的贡献之和(对\(998244353\)......
  • java 中文乱码问题解决思路
    碰到中文乱码,引起的原因一般为,在编写程序的时候的编码方式与查看的时候的编码方式不一致,从而导致了中文乱码。碰到这种问题,首先要做的就是查看自己编码方式,以String为例St......
  • 2022.11.2 模拟赛题解
    简要题意给定一棵\(n\)个节点的有根树,树根为\(1\)号节点,每个结点有一个权值\(a_i(|a_i|\leq10^9)\),求包含\(1\)的前\(k\)小的连通块的权值。简要题解前置内......
  • 11.2 解题报告&CSP-S 2022题解
    T1用时:\(1\)h期望得分:\(70\)~\(80\)实际得分:\(55\)这题考场写了个常数比较小的\(O(n^3)\)的做法,期望得分\(75\)左右,但是由于bfs忘记打标记导致MLE和TLE,挂......
  • P8671 [蓝桥杯 2018 国 AC] 约瑟夫环 题解
    约瑟夫环有\(\mathcalO(n)\)做法相信大家都知道。这里就不在介绍了,这里给出一个不知道这个结论的\(\mathcalO(n\logn)\)简单做法。考虑直接模拟题意,每次循环往后数......
  • [题解]CF1327F
    首先拆位,然后考虑限制会带来什么。要求与起来是\(1\)的必须全是\(1\),差分打个标记。要求与起来是\(0\)的必须至少有一个\(0\),考虑如何计数。计数问题有可能是动态......
  • CF1729G Cut Substrings 题解
    CF1729GCutSubstrings给出两个字符串\(s,t\),每次可以将字符串\(s\)中任意一个为\(t\)的子串删除,删除位置的字符变为空格(或理解为无实义)。求最少删除几次可以使得......
  • SOJ1669 题解
    题意传送门给定长度为\(N\)的数组\(a\)与\(Q\)个区间,还有一个整数\(M\)。你可以将至多\(M\)个\(a_i\)个变为\(0\),求\[\sum_{i=1}^Q\max_{l_i\lej\ler......
  • CF10E Greedy Change 题解
    http://codeforces.com/problemset/problem/10/E题意给出货币系统\(\{c_n\}\)满足\(c_1>c_2>\cdots>c_n=1\),请找到最小的\(x\)使贪心算法需要的货币数目比最优解多......