[ARC087D] Squirrel Migration 补题记录
题目链接
简要题意:
给你一个\(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\) 可以得到最大的构造方案是:
\]
接下来考虑容斥求方案数。
我们设 \(f_i\) 表示有 \(i\) 个数不满足条件,其他随便选的方案数。
那么:
\]
至于为什么有 \((n-i)!\) 是因为剩下的随便排列都是可以的。
我们考虑每一个与 \(\text{root}\) 连边的子树,设其大小为 \(\text{size}\) 。
可以得到这个子树中
\]
也是比较好理解的,小学乘法原理即可。
最后背包一下,具体可看代码。
#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 补题记录的更多相关文章
- 【补题记录】ZJU-ICPC Summer Training 2020 部分补题记录
补题地址:https://zjusummer.contest.codeforces.com/ Contents ZJU-ICPC Summer 2020 Contest 1 by Group A Pr ...
- 【JOISC 2020 补题记录】
目录 Day 1 Building 4 Hamburg Steak Sweeping Day 2 Chameleon's Love Making Friends on Joitter is Fun R ...
- 【cf补题记录】Codeforces Round #608 (Div. 2)
比赛传送门 再次改下写博客的格式,以锻炼自己码字能力 A. Suits 题意:有四种材料,第一套西装需要 \(a\).\(d\) 各一件,卖 \(e\) 块:第二套西装需要 \(b\).\(c\).\ ...
- 【cf补题记录】Codeforces Round #607 (Div. 2)
比赛传送门 这里推荐一位dalao的博客-- https://www.cnblogs.com/KisekiPurin2019/ A:字符串 B:贪心 A // https://codeforces.c ...
- Codeforces 1214 F G H 补题记录
翻开以前打的 #583,水平不够场上只过了五题.最近来补一下题,来记录我sb的调试过程. 估计我这个水平现场也过不了,因为前面的题已经zz调了好久-- F:就是给你环上一些点,两两配对求距离最小值. ...
- Yahoo Programming Contest 2019 补题记录(DEF)
D - Ears 题目链接:D - Ears 大意:你在一个\(0-L\)的数轴上行走,从整数格出发,在整数格结束,可以在整数格转弯.每当你经过坐标为\(i-0.5\)的位置时(\(i\)是整数),在 ...
- Codeforces 补题记录
首先总结一下前段时间遇到过的一些有意思的题. Round #474 (Div. 1 + Div. 2, combined) Problem G 其实关键就是n这个数在排列中的位置. 这样对于一个排 ...
- 【补题记录】NOIp-提高/CSP-S 刷题记录
Intro 众所周知原题没写过是很吃亏的,突然发现自己许多联赛题未补,故开此坑. 在基本补完前会持续更新,希望在 NOIp2020 前填完. 虽然是"联赛题",但不少题目还是富有思 ...
- ZJUT11 多校赛补题记录
牛客第一场 (通过)Integration (https://ac.nowcoder.com/acm/contest/881/B) (未补)Euclidean Distance (https://ac ...
随机推荐
- 【ASP.NET Core】自己编程来生成自签名的服务器证书
如果项目不大,或者是客户公司内部使用,或者不想花钱购买证书,又或者用于开发阶段测试--完全可以使用自签名证书. 所谓自签,就是自己给自己签名颁发的证书,自给自足,丰衣足食. 生成证书的方法和工具很多, ...
- Python图像处理丨OpenCV+Numpy库读取与修改像素
摘要:本篇文章主要讲解 OpenCV+Numpy 图像处理基础知识,包括读取像素和修改像素. 本文分享自华为云社区<[Python图像处理] 二.OpenCV+Numpy库读取与修改像素> ...
- XCTF练习题---MISC---Get-the-key.txt
XCTF练习题---MISC---Get-the-key.txt flag:SECCON{@]NL7n+-s75FrET]vU=7Z} 解题步骤: 1.观察题目,下载附件 2.拿到手以后直接惊呆,挺大 ...
- 基于DSP_CPLD_aP8942A_LM1791的语音控制
语音驱动程序 drv_voice.c 语音服务程序 srv_voice.c 1.先运行初始化函数,主要是设置初始音量,并建立一个软件定时器来,以10ms的周期来调用语音播放函数. 1 void s ...
- 购物车+ATM项目(图形化)
项目下载 项目目录结构 运行效果 seetings.py import logging import logging.config # 定义日志输出格式 开始 import os standard_f ...
- 华为OPS,自定义命令,动态执行命令
OPS 开放可编程系统OPS(Open Programmability System)是指设备通过提供统一的应用程序接口API(Application Programming Interfa ...
- spring boot 集成 rabbitmq 指南
先决条件 rabbitmq server 安装参考 一个添加了 web 依赖的 spring boot 项目 我的版本是 2.5.2 添加 maven 依赖 <dependency> &l ...
- 【算法】归并排序(Merge Sort)(五)
归并排序(Merge Sort) 归并排序是建立在归并操作上的一种有效的排序算法.该算法是采用分治法(Divide and Conquer)的一个非常典型的应用.将已有序的子序列合并,得到完全有序的序 ...
- 资讯:IEEE1
IEEE 2020 年 12 大技术趋势:边缘计算.量子计算.AI.数字孪生等 2020-02-06 以下是对2020年12大技术趋势的预测.IEEE计算机协会自2015年以来一直在预测技术趋势,其年 ...
- 好客租房23-react组件的两种创建方式(抽离为独立js)
2.3抽离为单独组件 组件作为一个单独的个体,一般把每个组件放在单独的js中文件中 1创建hello.js 2在hello.js中导入React 3创建组件(函数或者类) hello.js子组件 // ...