题目链接

简要题意:

给你一个\(N\)个节点的树,求一个\(1\cdots N\)的排列\((p_1,p_2,\cdots p_N)\) ,使得\(\sum dist(i,p_i)\)最大。

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

分析

先考虑怎么构造出 \(\sum dist(i,p_i)\) 最大的 \(p\) 。

先取出一条边,把它断开,使得原树分成两个部分 \(S_1\) 和 \(S_2\) 。

在最多的情况下,每一个都会走到另一个集合,所以路过切断边的次数是 \(2\times\min\{|S_1|,|S_2|\}\) 。

现在取出当前树的重心,至于为什么是重心:

考虑对于每一条边的贡献,及是之前讲的 \(2\times\min\{|S_1|,|S_2|\}\) ,我们要让贡献最大,显然要让 \(|S_1|\) 和 \(|S_2|\) 尽可能平衡。

自然而然就可以想到重心。

我们设当前子树为 \(S\) ,对于子树内的节点 \(u\) 可以得到最大的构造方案是:

\[\forall u\in S,p_u\notin S
\]

接下来考虑容斥求方案数。

我们设 \(f_i\) 表示有 \(i\) 个数不满足条件,其他随便选的方案数。

那么:

\[Ans = \sum_{i=0}^n(-1)^if_i(n-i)!
\]

至于为什么有 \((n-i)!\) 是因为剩下的随便排列都是可以的。

我们考虑每一个与 \(\text{root}\) 连边的子树,设其大小为 \(\text{size}\) 。

可以得到这个子树中

\[f_i=C_{\text{size}}^i\prod_{j=size-i+1}^jj
\]

也是比较好理解的,小学乘法原理即可。

最后背包一下,具体可看代码。

#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm> #define file(a) freopen(a".in", "r", stdin), freopen(a".out", "w", stdout) #define Enter putchar('\n')
#define quad putchar(' ') #define int long long
const int N = 5005;
const int mod = 1e9 + 7; int n, siz[N], w[N], root, fac[N], f[N], ans, inv[N];
std::vector <int> dis[N]; inline int power(int a, int n);
inline int C(int n, int m);
inline void get_root(int now, int father);
inline void dfs(int now, int father); signed main(void) {
// file("AT3728");
f[0] = 1; fac[0] = 1; inv[0] = 1;
std::cin >> n;
for (int i = 1; i <= n; i++)
fac[i] = fac[i - 1] * i % mod;
inv[n] = power(fac[n], mod - 2);
for (int i = n - 1; i >= 1; i--)
inv[i] = inv[i + 1] * (i + 1) % mod;
for (int i = 1, x, y; i < n; i++) {
scanf("%lld %lld", &x, &y);
dis[x].emplace_back(y);
dis[y].emplace_back(x);
}
get_root(1, 0);
memset(siz, 0, sizeof(siz));
dfs(root, 0);
for (int t : dis[root]) {
int x = siz[t];
for (int j = n; j >= 0; j--) {
for (int k = 1; k <= std::min(j, x); k++) {
int mul = C(x, k) * fac[x] % mod * inv[x - k] % mod;
f[j] = (f[j] + f[j - k] * mul % mod) % mod;
}
}
}
for (int i = 0; i <= n; i++) {
int flag = 1, num;
if (i % 2 == 1) flag = -1;
num = f[i] * fac[n - i] % mod;
ans = ans + flag * num;
ans = (ans % mod + mod) % mod;
}
std::cout << ans << std::endl;
return 0;
} inline int power(int a, int n) {
int ret = 1;
while (n) {
if (n & 1) ret = ret * a % mod;
a = a * a % mod;
n /= 2;
}
return ret;
}
inline int C(int n, int m) {
if (n < m) return 0;
int ret = fac[n];
ret = ret * inv[m] % mod;
ret = ret * inv[n - m] % mod;
return ret;
}
inline void get_root(int now, int father) {
siz[now] = 1; w[now] = 0;
for (int t : dis[now]) {
if (t == father) continue;
get_root(t, now);
siz[now] += siz[t];
w[now] = std::max(w[now], siz[t]);
}
w[now] = std::max(w[now], n - siz[now]);
if (w[now] <= n / 2) root = now;
}
inline void dfs(int now, int father) {
siz[now] = 1;
for (int t : dis[now]) {
if (t == father) continue;
dfs(t, now);
siz[now] += siz[t];
}
}

[ARC087D] Squirrel Migration 补题记录的更多相关文章

  1. 【补题记录】ZJU-ICPC Summer Training 2020 部分补题记录

    补题地址:https://zjusummer.contest.codeforces.com/ Contents ZJU-ICPC Summer 2020 Contest 1 by Group A Pr ...

  2. 【JOISC 2020 补题记录】

    目录 Day 1 Building 4 Hamburg Steak Sweeping Day 2 Chameleon's Love Making Friends on Joitter is Fun R ...

  3. 【cf补题记录】Codeforces Round #608 (Div. 2)

    比赛传送门 再次改下写博客的格式,以锻炼自己码字能力 A. Suits 题意:有四种材料,第一套西装需要 \(a\).\(d\) 各一件,卖 \(e\) 块:第二套西装需要 \(b\).\(c\).\ ...

  4. 【cf补题记录】Codeforces Round #607 (Div. 2)

    比赛传送门 这里推荐一位dalao的博客-- https://www.cnblogs.com/KisekiPurin2019/ A:字符串 B:贪心 A // https://codeforces.c ...

  5. Codeforces 1214 F G H 补题记录

    翻开以前打的 #583,水平不够场上只过了五题.最近来补一下题,来记录我sb的调试过程. 估计我这个水平现场也过不了,因为前面的题已经zz调了好久-- F:就是给你环上一些点,两两配对求距离最小值. ...

  6. Yahoo Programming Contest 2019 补题记录(DEF)

    D - Ears 题目链接:D - Ears 大意:你在一个\(0-L\)的数轴上行走,从整数格出发,在整数格结束,可以在整数格转弯.每当你经过坐标为\(i-0.5\)的位置时(\(i\)是整数),在 ...

  7. Codeforces 补题记录

    首先总结一下前段时间遇到过的一些有意思的题. Round #474 (Div. 1 + Div. 2, combined)   Problem G 其实关键就是n这个数在排列中的位置. 这样对于一个排 ...

  8. 【补题记录】NOIp-提高/CSP-S 刷题记录

    Intro 众所周知原题没写过是很吃亏的,突然发现自己许多联赛题未补,故开此坑. 在基本补完前会持续更新,希望在 NOIp2020 前填完. 虽然是"联赛题",但不少题目还是富有思 ...

  9. ZJUT11 多校赛补题记录

    牛客第一场 (通过)Integration (https://ac.nowcoder.com/acm/contest/881/B) (未补)Euclidean Distance (https://ac ...

随机推荐

  1. ASP.NETCore统一处理404错误都有哪些方式?

    当未找到网页并且应用程序返回 404 错误时,ASP.NET Core MVC 仅呈现通用浏览器错误页面,如下图所示 这不是很优雅,是吗? 我们平时看到的404页面一般是这样的 还有这样的 试了下京东 ...

  2. 【SpringBoot实战】实现WEB的常用功能

    前言 通常在 Web 开发中,会涉及静态资源的访问支持.视图解析器的配置.转换器和格式化器的定制.文件上传下载等功能,甚至还需要考虑到与Web服务器关联的 Servlet相关组件的定制.Spring ...

  3. 详解MySQL索引

    原文链接详解MySQL索引 索引介绍 索引是帮助MySQL高效获取数据的数据结构.在数据之外,数据库系统还维护着一个用来查找数据的数据结构,这些数据结构指向着特定的数据,可以实现高级的查找算法. 本文 ...

  4. 为什么不建议给MySQL设置Null值?《死磕MySQL系列 十八》

    大家好,我是咔咔 不期速成,日拱一卒 之前ElasticSearch系列文章中提到了如何处理空值,若为Null则会直接报错,因为在ElasticSearch中当字段值为null时.空数组.null值数 ...

  5. Java学习笔记-基础语法Ⅵ-异常

    异常 对于异常,JVM默认处理方案为:把异常名称.异常原因以及异常出现的位置等信息输出在控制台,并且程序停止执行 异常处理方式一:try ... catch public class Demo { p ...

  6. GIL与普通互斥锁区别,死锁现象,信号量,event事件,进程池与线程池,协程

    GIL与普通互斥锁区别 GIL锁和互斥锁的异同点 相同: 都是为了解决解释器中多个线程资源竞争的问题 异: 1.互斥锁是Python代码层面的锁,解决Python程序中多线程共享资源的问题(线程数据共 ...

  7. MVC 与 Vue

    MVC 与 Vue 本文写于 2020 年 7 月 27 日 首先有个问题:Vue 是 MVC 还是 MVVM 框架? 维基百科告诉我们:MVVM 是 PM 的变种,而 PM 又是 MVC 的变种. ...

  8. c# DateTime 格式化输出字符串

    DateTime 输出字符串 带 T,结尾 +08:00 $"{DateTime.Now:O}"; // 2020-12-20T16:11:18.2353338+08:00 $&q ...

  9. 806. Number of Lines To Write String - LeetCode

    Question 806. Number of Lines To Write String Solution 思路:注意一点,如果a长度为4,当前行已经用了98个单元,要另起一行. Java实现: p ...

  10. undefined与null与?. ??

    undefined: undefined是全局对象的一个属性,在一下情况下都是undefined: 当一个变量没有被赋值: 当一个函数没有返回值: 当某个对象不存在某个属性却去访问: 当函数定义了形参 ...