Solution -「CF 917D」Stranger Trees
\(\mathcal{Description}\)
Link.
给定一棵包含 \(n\) 个点的有标号树,求与这棵树重合恰好 \(0,1,\cdots,n-1\) 条边的树的个数,对 \(10^9+7\) 取模。
\(n\le100\)。
\(\mathcal{Solution}\)
\(\mathcal{Case~1}\)
考虑把“是否是原树上的边”看做一种权值,相当于求完全图的生成树。具体地,令完全图中,原树有的边的权值为 \(1\),否则为 \(x\),用多项式暴力维护求行列式,取答案的前若干项即为答案。
\(\mathcal O(n^5)\),原题过不了 qwq。不过可以用带入 \(x\) 再插值的方法优化为 \(\mathcal O(n^4)\)。
\(\mathcal{Case~2}\)
尝试带着二项式反演在树上 DP 计数。若把原树分为若干个联通块,块的大小为 \(a_1,a_2,\cdots,a_m\),则把这些块连成树的方案数为
\]
Prufer 或 Matrix-Tree 可证。
基于此,令 \(f(u,i,j)\) 表示 \(u\) 子树内分为 \(i\) 个联通块,其中 \(u\) 所在块的大小为 \(j\) 的方案数。自然得到一个 \(\mathcal O(n^3)\) 的转移。
继续优化,考虑 \(\prod_ia_i\) 的组合意义——在每个块内选一个关键点。所以可以设 \(f(u,i,0/1)\) 表示 \(u\) 子树内分为 \(i\) 个联通块,其中 \(u\) 所在联通块是否已选关键点时的方案数。\(\mathcal O(n^3)\) 转移。
最后,\(f(\textit{root},k,1)\) 即表示钦定新树与原树重合某 \(n-k\) 条边的方案数,记为 \(g(n-k)\)。令 \(i\) 的答案为 \(h(i)\),则 \(g\) 与 \(h\) 构成反演关系:
\]
所以有
\]
以上,\(\mathcal O(n^2)\) 即可求出答案。
\(\mathcal{Code}\)
/* Clearink */
#include <cstdio>
#define rep( i, l, r ) for ( int i = l, repEnd##i = r; i <= repEnd##i; ++i )
#define per( i, r, l ) for ( int i = r, repEnd##i = l; i >= repEnd##i; --i )
const int MAXN = 100, MOD = 1e9 + 7;
int n, ecnt, head[MAXN + 5], comb[MAXN + 5][MAXN + 5];
int siz[MAXN + 5], f[MAXN + 5][MAXN + 5][2], g[MAXN + 5];
struct Edge { int to, nxt; } graph[MAXN * 2 + 5];
inline int mul( const long long a, const int b ) { return a * b % MOD; }
inline int sub( int a, const int b ) { return ( a -= b ) < 0 ? a + MOD : a; }
inline void subeq( int& a, const int b ) { ( a -= b ) < 0 && ( a += MOD ); }
inline int add( int a, const int b ) { return ( a += b ) < MOD ? a : a - MOD; }
inline void addeq( int& a, const int b ) { ( a += b ) >= MOD && ( a -= MOD ); }
inline int mpow( int a, int b ) {
int ret = 1;
for ( ; b; a = mul( a, a ), b >>= 1 ) ret = mul( ret, b & 1 ? a : 1 );
return ret;
}
inline void link( const int u, const int v ) {
graph[++ecnt] = { v, head[u] }, head[u] = ecnt;
graph[++ecnt] = { u, head[v] }, head[v] = ecnt;
}
inline void initC() {
comb[0][0] = 1;
rep ( i, 1, n ) {
comb[i][0] = 1;
rep ( j, 1, i ) comb[i][j] = add( comb[i - 1][j - 1], comb[i - 1][j] );
}
}
inline void getDP( const int u, const int fa ) {
f[u][1][0] = f[u][1][1] = siz[u] = 1;
int tmp[MAXN + 5][2] = {}, ( *fcur )[2] = f[u];
for ( int e = head[u], v; e; e = graph[e].nxt ) {
if ( ( v = graph[e].to ) != fa ) {
getDP( v, u );
int ( *fsub )[2] = f[v];
rep ( i, 1, siz[u] ) rep ( j, 1, siz[v] ) {
addeq( tmp[i + j][0], mul( fcur[i][0], fsub[j][1] ) );
addeq( tmp[i + j][1], mul( fcur[i][1], fsub[j][1] ) );
addeq( tmp[i + j - 1][0], mul( fcur[i][0], fsub[j][0] ) );
addeq( tmp[i + j - 1][1], add( mul( fcur[i][0], fsub[j][1] ),
mul( fcur[i][1], fsub[j][0] ) ) );
}
siz[u] += siz[v];
rep ( i, 1, siz[u] ) {
fcur[i][0] = tmp[i][0], tmp[i][0] = 0;
fcur[i][1] = tmp[i][1], tmp[i][1] = 0;
}
}
}
}
int main() {
scanf( "%d", &n ), initC();
for ( int i = 1, u, v; i < n; ++i ) {
scanf( "%d %d", &u, &v );
link( u, v );
}
getDP( 1, 0 );
rep ( i, 1, n ) {
g[n - i] = mul( f[1][i][1], i < 2 ? 1 : mpow( n, i - 2 ) );
}
g[n - 1] = 1;
rep ( i, 0, n - 1 ) {
int ans = 0;
rep ( j, i, n - 1 ) {
( ( j - i ) & 1 ? subeq : addeq )( ans,
mul( comb[j][i], g[j] ) );
}
printf( "%d%c", ans, i < n - 1 ? ' ' : '\n' );
}
return 0;
}
Solution -「CF 917D」Stranger Trees的更多相关文章
- Solution -「CF 1237E」Balanced Binary Search Trees
\(\mathcal{Description}\) Link. 定义棵点权为 \(1\sim n\) 的二叉搜索树 \(T\) 是 好树,当且仅当: 除去最深的所有叶子后,\(T\) 是满的: ...
- Solution -「CF 1342E」Placing Rooks
\(\mathcal{Description}\) Link. 在一个 \(n\times n\) 的国际象棋棋盘上摆 \(n\) 个车,求满足: 所有格子都可以被攻击到. 恰好存在 \(k\ ...
- Solution -「CF 1622F」Quadratic Set
\(\mathscr{Description}\) Link. 求 \(S\subseteq\{1,2,\dots,n\}\),使得 \(\prod_{i\in S}i\) 是完全平方数,并最 ...
- Solution -「CF 923F」Public Service
\(\mathscr{Description}\) Link. 给定两棵含 \(n\) 个结点的树 \(T_1=(V_1,E_1),T_2=(V_2,E_2)\),求一个双射 \(\varph ...
- Solution -「CF 923E」Perpetual Subtraction
\(\mathcal{Description}\) Link. 有一个整数 \(x\in[0,n]\),初始时以 \(p_i\) 的概率取值 \(i\).进行 \(m\) 轮变换,每次均匀随机 ...
- Solution -「CF 1586F」Defender of Childhood Dreams
\(\mathcal{Description}\) Link. 定义有向图 \(G=(V,E)\),\(|V|=n\),\(\lang u,v\rang \in E \Leftrightarr ...
- Solution -「CF 623E」Transforming Sequence
题目 题意简述 link. 有一个 \(n\) 个元素的集合,你需要进行 \(m\) 次操作.每次操作选择集合的一个非空子集,要求该集合不是已选集合的并的子集.求操作的方案数,对 \(10^9 ...
- Solution -「CF 1023F」Mobile Phone Network
\(\mathcal{Description}\) Link. 有一个 \(n\) 个结点的图,并给定 \(m_1\) 条无向带权黑边,\(m_2\) 条无向无权白边.你需要为每条白边指定边权 ...
- Solution -「CF 599E」Sandy and Nuts
\(\mathcal{Description}\) Link. 指定一棵大小为 \(n\),以 \(1\) 为根的有根树的 \(m\) 对邻接关系与 \(q\) 组 \(\text{LCA}\ ...
随机推荐
- redis中文乱码问题
1.可以直接打开dos指令框输入指令进去redis数据库,因为在安装的时候就已经勾选了配置默认的环境变量. 2.可以输入ip进去,redis-cli.exe -h 192.168.32.8 -p 63 ...
- HDU 2673-shǎ崽 OrOrOrOrz(C语言描述)
问题描述 问题是: 为您提供了一系列不同的整数, 请选择 "数字" 如下: 首先选择最大的, 然后是最小的, 然后是第二个最大的, 第二个最小的. 直到所有的数字被选中.例如, 给 ...
- 《Go组件设计与实现》-netpoll的总结
主要针对字节跳动的netpoll网络库进行总结.netpoll网络库相比于go本身的net标准库更适合高并发场景. 基础知识 netpoll与go.net库一样使用epoll这种IO多路复用机制处理网 ...
- Cesium入门5 - Cesium ion
Cesium入门5 - Cesium ion Cesium中文网:http://cesiumcn.org/ | 国内快速访问:http://cesium.coinidea.com/ Cesium io ...
- 主键约束(primary key 简称PK)
7.5.主键约束 主键约束相关术语 主键约束 主键字段:字段添加了主键约束,叫主键字段 主键值:主键字段中的每个值都叫主键值 什么是主键? 主键值是每一行记录的唯一标识(主键值是每一行记录的身份证号) ...
- python数据操作--8
转:https://www.tuicool.com/wx/MB7nieb 数据类型 整数, 浮点数, 字符串, 布林值(True,False) 列表(list), 不可变的列表 Tuple, 集合(没 ...
- 一起玩转玩转LiteOS组件:TinyFrame
摘要:TinyFrame是一个简单的用于解析串口(如 UART.telnet.套接字等)通信数据帧的库. 本文分享自华为云社区<LiteOS组件尝鲜-玩转TinyFrame>,作者:Lio ...
- React之react-router(connected-react-router/react-router-dom)
文档: react-router-dom官方文档:https://reacttraining.com/react-router/web/guides/quick-start connected-rea ...
- 微服务架构 | 10.1 使用 Sleuth 追踪服务调用链
目录 前言 1. Sleuth 基础知识 1.1 Sleuth 原理 2. 在服务中使用 Sleuth 追踪 2.1 引入 pom.xml 依赖文件 2.2 查看日志信息 最后 前言 参考资料: &l ...
- v76.01 鸿蒙内核源码分析(共享内存) | 进程间最快通讯方式 | 百篇博客分析OpenHarmony源码
百篇博客分析|本篇为:(共享内存篇) | 进程间最快通讯方式 进程通讯相关篇为: v26.08 鸿蒙内核源码分析(自旋锁) | 当立贞节牌坊的好同志 v27.05 鸿蒙内核源码分析(互斥锁) | 同样 ...