Maximum Diameter 题解
题目大意
定义长度为 \(n\) 的序列 \(a\) 的权值为:
- 所有的 \(n\) 个点的第 \(i\) 个点的度数为 \(a_i\) 的树的直径最大值,如果不存在这样的树,其权值为 \(0\)。
给定 \(n\),求所有长度为 \(n\) 的序列的权值和。
思路分析
\(n\) 个点的树的边数为 \(n-1\),总度数为 \(2n-2\),故序列 \(a\) 的权值不为 \(0\) 当且仅当 \(\sum a=2n-2\) 且 \(a_i>0\),因此我们只需要考虑这样的序列即可。
考虑如何根据给定序列构造出直径最大的树,设 \(a\) 中有 \(k\) 个 \(1\),也就是树上有 \(k\) 个叶子节点,那么我们可以将剩下的 \(n-k\) 个节点全部串在一起,再在两端放上两个叶子节点,用 \(n-k+2\) 个点构造出一条长 \(n-k+1\) 的链,其余的叶子节点挂在链上,显然这是最优方案,直径为 \(n-k+1\)。
考虑计数。枚举 \(k\),那么叶子节点的选择方案数为 \({n \choose k}\)。而非叶子节点的度数必须大于 \(1\),且有 \(n-k\) 个,又因为剩余的可用度数为 \(2n-2-k\),所以这个问题等价于将 \(2n-2-k\) 个相同的球放在 \(n-k\) 个盒子里,且每个盒子的球必须大于 \(1\),由插板法易得其方案数为:
\]
再算上直径产生的贡献,故我们所求式即:
\]
这个式子可以 \(O(n)\) 计算,但这显然不够,我们需要继续化简。
我们有以下两个式子:
吸收恒等式:\(k{n\choose k}=n{n-1\choose k-1}\)
范德蒙德卷积:\(\sum\limits_{i=0}^k{n\choose i}{m\choose k-i}={n+m\choose k}\)
一式可以直接拆组合数简单证明,二式通过组合意义显然成立。
然后我们就可以通过以上两个式子对所求式进行化简了:
\sum_{k=1}^n{n\choose k}{n-3\choose k-2}(n-k+1)&=
-\sum_{k=1}^n{n\choose k}{n-3\choose k-2}(k-2+1-n)\\&=
-\sum_{k=1}^n{n\choose k}{n-3\choose k-2}(k-2)+(n-1)\sum_{k=1}^n{n\choose k}{n-3\choose k-2}\\&=
(n-1)\sum_{k=1}^n{n\choose k}{n-3\choose k-2}-(n-3)\sum_{k=1}^n{n\choose k}{n-4\choose k-3}\\&=
(n-1)\sum_{k=1}^n{n\choose k}{n-3\choose n-k-1}-(n-3)\sum_{k=1}^n{n\choose k}{n-4\choose n-k-1}\\&=
(n-1){2n-3\choose n-1}-(n-3){2n-4\choose n-3}
\end{aligned}\]
化到这样就可以 \(O(1)\) 计算了,只需要 \(O(n)\) 预处理组合数就行了。
代码
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
const int N = 2002000, L = 2000000, mod = 998244353;
#define int long long
int fac[N], inv[N];
int T, n;
int q_pow(int a, int b){
int res = 1;
while (b) {
if (b & 1) res = (res * a) % mod;
a = (a * a) % mod;
b >>= 1;
}
return res;
}
int C(int n, int m){
if(n < m || n < 0 || m < 0) return 0;
return fac[n] * (inv[m] * inv[n - m] % mod) % mod;
}
signed main(){
fac[0] = 1;
for (int i = 1; i <= L; i ++) fac[i] = fac[i - 1] * i % mod;
inv[L] = q_pow(fac[L], mod - 2);
for (int i = L; i >= 1; i --) inv[i - 1] = inv[i] * i % mod;
scanf("%lld", &T);
while (T --) {
scanf("%lld", &n);
int res1 = (n - 1) * C(2 * n - 3, n - 1) % mod;
int res2 = (n - 3) * C(2 * n - 4, n - 3) % mod;
int ans = (res1 - res2 + mod) % mod;
cout << ans << '\n';
}
return 0;
}
Maximum Diameter 题解的更多相关文章
- Educational Codeforces Round 55 (Rated for Div. 2):D. Maximum Diameter Graph
D. Maximum Diameter Graph 题目链接:https://codeforces.com/contest/1082/problem/D 题意: 给出n个点的最大入度数,要求添加边构成 ...
- Educational Codeforces Round 55 (Rated for Div. 2) D. Maximum Diameter Graph (构造图)
D. Maximum Diameter Graph time limit per test2 seconds memory limit per test256 megabytes inputstand ...
- C#版 - Leetcode 414. Third Maximum Number题解
版权声明: 本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. C#版 - L ...
- Codeforces 1082 D. Maximum Diameter Graph-树的直径-最长链-构造题 (Educational Codeforces Round 55 (Rated for Div. 2))
D. Maximum Diameter Graph time limit per test 2 seconds memory limit per test 256 megabytes input st ...
- [CF1082D]Maximum Diameter Graph
题目描述 Description Graph constructive problems are back! This time the graph you are asked to build sh ...
- CF1082D:Maximum Diameter Graph (简单构造)
Graph constructive problems are back! This time the graph you are asked to build should match the fo ...
- [LeetCode]Maximum Subarray题解
Maximum Subarray: Find the contiguous subarray within an array (containing at least one number) whic ...
- CodeForces 1082 D Maximum Diameter Graph
题目传送门 题意:现在有n个点,每个点的度数最大为di,现在要求你构成一棵树,求直径最长. 题解:把所有度数为2的点先扣出来,这些就是这颗树的主干,也就是最长的距离. 然后我们把度数为2的点连起来,之 ...
- D. Maximum Diameter Graph 贪心+图论+模拟
题意:给出n个点的度数列 上限(实际点可以小于该度数列)问可以构造简单路最大长度是多少(n个点要连通 不能有平行边.重边) 思路:直接构造一条长链 先把度数为1的点 和度数大于1的点分开 先把度数 ...
- Codeforces 1082D Maximum Diameter Graph (贪心构造)
<题目链接> 题目大意:给你一些点的最大度数,让你构造一张图,使得该图的直径最长,输出对应直径以及所有的边. 解题分析:一道比较暴力的构造题,首先,我们贪心的想,要使图的直径最长,肯定是尽 ...
随机推荐
- 我在使用Winform7.0开发海康相机应用的时候系统悄无声息的退出
一.简介 1.说明一下 最近,我在开发一个玻璃幕墙检测的项目,这个项目需要使用到海康的相机系统.业务是这样的,相机按着指定的坐标,扫描玻璃幕墙的每块玻璃,通过算法查看是否有损坏的,如果有就发出报警信息 ...
- 除了参数,ref关键字还可以用在什么地方?
<老生常谈:值类型 V.S. 引用类型>中花了很大的篇幅介绍ref参数针对值类型和引用类型变量的传递.在C#中,除了方法的ref参数,我们还有很多使用ref关键字传递引用/地址的场景,本篇 ...
- MySQL数据库的集群方案
读写分离结构(主从) 读多写少,也就是对数据库读取数据的压力比较大. 其中一个是主库,负责写入数据,成为写库:其他都是从库,负责读取数据,成为读库. 对我们的要求: 读库和写库的数据一致: 写数据必须 ...
- dash构建多页应用
dash 构建多页面应用一种方案 本方案对dash官网多页面案例使用dash_bootstrap_components案例进行优化与测试,效果如下 项目代码结构如下 │ app.py │ ├─asse ...
- (四) MdbCluster分布式内存数据库——业务消息处理
(四) MdbCluster分布式内存数据库--业务消息处理 上篇:(三) MdbCluster分布式内存数据库--节点状态变化及分片调整 离上次更新文章已有快5个月,我还是有点懒.但我们系统 ...
- centOS7 磁盘扩容(2T以上)
centOS7 磁盘扩容 1.安装parted分区工具 yum install -y parted 2.查看服务器分区情况 #fdisk -l 或者 lsblk 找到新增磁盘名称 例如/dev/sdb ...
- jenkins打包报错的排查思路与解决
背景 废话少说, 在新建一个jenkins流水线时, 碰到了打包死活无法成功的问题, 相关配置如下图 运行后最后的日志如图 定位问题 通过查看日志, 发现报错的模块是构建后执行shell的时候, 但是 ...
- 但因热爱,愿迎万难,OpenTiny 社区增加一枚前端程序媛贡献者🎉
我们非常高兴地宣布,OpenTiny Vue Playground 正式上线! 链接:https://opentiny.github.io/tiny-vue-playground/ 在此非常感谢 xi ...
- asp.net core之异常处理
在开发过程中,处理错误是一个重要的方面.ASP.NET Core提供了多种方式来处理错误,以确保应用程序的稳定性和可靠性. TryCatch TryCatch是最常见也是最基础的一种异常处理方式,只需 ...
- sudo提权操作
sudo提权操作 sudo sudo是linux系统管理指令,是允许系统管理员让普通用户执行一些或者全部的root命令的一个工具,如halt,reboot,su等等.这样不仅减少了root用户的登录 ...