CF917D Stranger Trees
CF917D Stranger Trees
给定一个树,对于每个\(k=0,1\cdots n-1\),问有多少个生成树与给定树有\(k\)条边重合。
矩阵树定理+高斯消元
我们答案为\(f_k\)。假设我们呢将原树上的边权设为\(x\),其他的边权设为\(1\),那么我们做一次矩阵树定理求出来的东西就是\(\displaystyle \sum_{i=0}^{n-1}f_i x^i\)。于是我们找\(n\)个不同的\(x\),然后高斯消元就行了。
代码:
#include<bits/stdc++.h>
#define ll long long
#define mod 1000000007
#define N 105
using namespace std;
inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}
int n;
ll a[N][N],d[N];
ll w[N][N];
ll c[N][N],ans[N];
ll ksm(ll t,ll x) {
ll ans=1;
for(;x;x>>=1,t=t*t%mod)
if(x&1) ans=ans*t%mod;
return ans;
}
void Gauss(ll a[N][N],int n) {
for(int i=1;i<=n;i++) {
for(int j=i+1;j<=n;j++) {
ll t=ksm(a[i][i],mod-2)*a[j][i]%mod;
for(int k=i;k<=n+1;k++) a[j][k]=(a[j][k]-t*a[i][k]%mod+mod)%mod;
}
}
}
int main() {
n=Get();
for(int i=1;i<n;i++) {
int x=Get(),y=Get();
a[x][y]=a[y][x]=1;
d[x]++,d[y]++;
}
for(int v=1;v<=n;v++) {
memset(w,0,sizeof(w));
for(int i=1;i<=n;i++) {
for(int j=1;j<=n;j++) {
if(i==j) w[i][j]=d[i]*v+n-1-d[i];
else if(a[i][j]) w[i][j]=mod-v;
else w[i][j]=mod-1;
}
}
Gauss(w,n-1);
c[v][n+1]=1;
for(int i=1;i<n;i++) c[v][n+1]=c[v][n+1]*w[i][i]%mod;
ll now=1;
for(int i=1;i<=n;i++,now=now*v%mod) c[v][i]=now;
}
Gauss(c,n);
for(int i=n;i>=1;i--) {
for(int j=i+1;j<=n;j++) {
c[i][n+1]=(c[i][n+1]-ans[j]*c[i][j]%mod+mod)%mod;
}
ans[i]=ksm(c[i][i],mod-2)*c[i][n+1]%mod;
}
for(int i=1;i<=n;i++) cout<<ans[i]<<" ";
return 0;
}
容斥原理+prufer序列
我们的原理就是选定\(k\)个边与原树重合,这样我们将原树分成了\(n-k\)个联通块。我们求出此时的生成树方案树,表示至少\(k\)条边重合的方案树,然后容斥就好了。
具体求法如下:
给定一颗森林,每个联通块的大小是\(a_i\),那么这个森林的生成树方案树我们也可以用\(prufer\)序列来求。将每个连通块视作点,设第\(i\)个块出现的次数为\(t_i\),则一个序列的答案为\(\prod a_i^{t_i}\)。
我们设所有\(prufer\)序列为\(P\),则我们有一下变换:
\displaystyle
ans&=(\prod_{i=1}^k a_i)\sum_{p\in P}\prod_{i=1}^{k-2}a_{p_i}\\
&=(\prod_{i=1}^k a_i)\prod_{i=1}^{k-2}\sum_{j=1}^ka_j\\
&=(\prod_{i=1}^k a_i)\prod_{i=1}^{k-2}n^{k-2}\\
\end{align}
\]
\(\sum_{p\in P}\prod_{i=1}^{k-2}a_{p_i}=\prod_{i=1}^{k-2}\sum_{j=1}^ka_j\)就是一个经典的和式变换。
得到上述的结论过后,我们就可以树形\(DP\)了。设\(f_{i,j,k}\)表示已\(i\)为根的子树中,分成了\(j\)个连通块,\(i\)所在的连通块的大小为\(k\)的生成树数量。
代码:
没写
CF917D Stranger Trees的更多相关文章
- CF917D. Stranger Trees & TopCoder13369. TreeDistance(变元矩阵树定理+高斯消元)
题目链接 CF917D:https://codeforces.com/problemset/problem/917/D TopCoder13369:https://community.topcoder ...
- CF917D Stranger Trees【矩阵树定理,高斯消元】
题目链接:洛谷 题目大意:给定一个$n$个节点的树$T$,令$ans_k=\sum_{T'}[|T\cap T'|=k]$,即有$k$条边重合.输出$ans_0,ans_1,\ldots,ans_{n ...
- [CF917D]Stranger Trees[矩阵树定理+解线性方程组]
题意 给你 \(n\) 个点的无向完全图,指定一棵树 \(S\),问有多少棵生成树和这棵树的公共边数量为 \(k\in[0,n-1]\) \(n\leq 100\) 分析 考虑矩阵树定理,把对应的树边 ...
- 【CF917D】Stranger Trees 树形DP+Prufer序列
[CF917D]Stranger Trees 题意:给你一棵n个点的树,对于k=1...n,问你有多少有标号的n个点的树,与给出的树有恰好k条边相同? $n\le 100$ 题解:我们先考虑容斥,求出 ...
- 【CF917D】Stranger Trees
题目 看题解的时候才突然发现\(zky\)讲过这道题啊,我现在怕不是一个老年人了 众所周知矩阵树求得是这个 \[\sum_{T}\prod_{e\in T}w_e\] 而我们现在的这个问题有些鬼畜了, ...
- 题解 CF917D 【Stranger Trees】
生成树计数问题用矩阵树定理来考虑. 矩阵树定理求得的为\(\sum\limits_T\prod\limits_{e\in T}v_e\),也就是所有生成树的边权积的和. 这题边是不带权的,应用矩阵树定 ...
- codeforces 917D Stranger Trees
题目链接 正解:矩阵树定理+拉格朗日插值. 一下午就搞了这一道题,看鬼畜英文题解看了好久.. 首先这题出题人给了两种做法,感觉容斥+$prufer$序列+$dp$的做法细节有点多所以没看,然而这个做法 ...
- Codeforces917D. Stranger Trees
$n \leq 100$的完全图,对每个$0 \leq K \leq n-1$问生成树中与给定的一棵树有$K$条公共边的有多少个,答案$mod \ \ 1e9+7$. 对这种“在整体中求具有某些特性的 ...
- 题解-Codeforces917D Stranger Trees
Problem \(\mathrm{Codeforces~917D}\) 题意概要:一棵 \(n\) 个节点的无向树.问在 \(n\) 个点的完全图中,有多少生成树与原树恰有 \(k\) 条边相同,对 ...
随机推荐
- Oracle 数据库导出数据泵(EXPDP)文件存放的位置
数据泵是服务器端工具,导出的文件是放在数据库所在的服务器上,当然我们知道可以通过directory目录对象来控制.目录对象默认有四个级别,当然是有优先级顺序的,优先级从上往下 1.每个文件单独的指定具 ...
- 10.QT-定时器
QObject定时器 需要头文件#include <QTimerEvent> 需要函数 int QObject::startTimer(int interval); //启动定时器,并设 ...
- Java_文件夹拷贝
一.思路 * 文件夹的拷贝 1.递归查找子孙级文件 2.文件复制 文件夹创建 二.代码 package com.ahd.File; import java.io.File; import java.i ...
- Eclipse中提示svn: is already locked的解决办法
eclipse的svn提交不了,报错.提示 svn: is already locked 解决办法:右键项目-------Team------Refresh/Cleanup
- redirection in linux
2>&1 # Redirects stderr to stdout. # Error messages get sent to same place as standard output ...
- 自动化运维经验谈,以及为什么Docker是革命性的
互联网+的需要 在信息越来越繁杂的互联网时代,公司所运行的项目越来越多,项目相关服务繁多,服务之间存在复杂的依赖关系,运维与管理任务越来越繁重,手工交付需要花费很多的人力与时间,且安全性和时效性均无法 ...
- java集合框架-List集合ArrayList和LinkedList详解
List 集合源码剖析 ✅ ArrayList 底层是基于数组,(数组在内存中分配连续的内存空间)是对数组的升级,长度是动态的. 数组默认长度是10,当添加数据超越当前数组长度时,就会进行扩容,扩容长 ...
- 前端常见算法的JS实现
1.冒泡排序 function bubbleSort(arr){ var i = 0, j = 0; for(i=1; i<arr.length; i++){ for(j=0; j<=ar ...
- Android TextView自动换行、排列错乱问题及解决
解决之前层次不齐的排版截图,如下图: 解决之后的整齐排版截图,如下图: 今天忽然发现android项目中的文字排版参差不齐的情况非常严重,不得不想办法解决一下 ...
- wap2app(十)--wap2app 添加原生底部导航,添加原生标题栏,填坑
一.添加原生标题栏 添加原生标题栏可以参照 <wap2app(六)-- wap2app的原生标题头无法隐藏>,具体如下: 1.打开 sitemap.json文件 --> page配置 ...