P5296 [北京省选集训2019]生成树计数

题意

求一个带权无向图所有生成树边权和的 \(k\) 次方的和。

思路

首先有一个结论:\(a^i\) 的 EGF 卷 \(b^i\) 的 EGF 等于 \((a+b)^i\) 的 EGF。即:

\[F(a)=\sum_{i=0}\frac{a^ix^i}{i!}\\
F(a+b)=F(a)*F(b)
\]

证明如下:

\[(a+b)^k=\sum_{i=0}^k{k\choose i}a^ib^{k-i}=\sum_{i=0}^k\frac{k!}{i!(k-i)!} a^ib^{k-i}\\
\Rightarrow \sum_{i=0}^k\frac{a^i}{i!}\frac{b^{k-i}}{(k-i)!}k!=(a+b)^k \\
\Rightarrow \sum_{i=0}^k\frac{a^i}{i!}\frac{b^{k-i}}{(k-i)!}=\frac{(a+b)^k}{k!}\\
\]

然后又有一个结论:度数矩阵减去邻接矩阵的余子式的行列式的值是图所有生成树边权积的和。其中,度数矩阵表示与其相连的边权的和,邻接矩阵为边权。这是矩阵树定理。

于是,我们将边权化为生成函数,然后利用矩阵树定理算出来答案的生成函数即可。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cctype>
#include<cstring>
#include<cmath>
using namespace std;
inline int read(){
int w=0,x=0;char c=getchar();
while(!isdigit(c))w|=c=='-',c=getchar();
while(isdigit(c))x=x*10+(c^48),c=getchar();
return w?-x:x;
}
namespace star
{
const int maxn=35,mod=998244353;
int n,k,mul[maxn],inv[maxn];
inline int fpow(int a,int b){int ans=1;for(;b;b>>=1,a=1ll*a*a%mod) if(b&1) ans=1ll*ans*a%mod;return ans;}
struct poly{
int a[maxn];
poly():a(){}
poly(int x):a(){for(int i=0,d=1;i<=k;i++,d=1ll*d*x%mod) a[i]=1ll*star::inv[i]*d%mod;}
int& operator [](const int &x){return a[x];}
const int &operator [](const int &x) const {return a[x];}
friend poly operator + (const poly& a,const poly& b) {
poly ans;
for(int i=0;i<=k;i++) ans[i]=(a[i]+b[i])%mod;
return ans;
}
friend poly operator - (const poly& a,const poly& b) {
poly ans;
for(int i=0;i<=k;i++) ans[i]=(a[i]-b[i]+mod)%mod;
return ans;
}
friend poly operator * (const poly& a,const poly& b) {
poly ans;
for(int i=0;i<=k;i++) for(int j=0;j<=i;j++) ans[i]=(ans[i]+1ll*a[j]*b[i-j])%mod;
return ans;
}
inline poly operator - () const {
poly ans;
for(int i=0;i<=k;i++) ans[i]=(mod-a[i])%mod;
return ans;
}
inline poly inv() const {
poly ans,res;
ans[0]=fpow(a[0],mod-2);
for(int i=1;i<=k;i++) res[i]=1ll*a[i]*ans[0]%mod;
for(int i=1;i<=k;i++) for(int j=1;j<=i;j++) ans[i]=(ans[i]+1ll*(mod-res[j])*ans[i-j])%mod;
return ans;
}
}a[maxn][maxn],ans;
inline void work(){
n=read()-1,k=read();
mul[0]=inv[0]=1;
for(int i=1;i<=k;i++) mul[i]=1ll*mul[i-1]*i%mod;
inv[k]=fpow(mul[k],mod-2);for(int i=k-1;i>0;i--) inv[i]=1ll*inv[i+1]*(i+1)%mod;
for(int i=0;i<=n;i++) for(int j=0;j<=n;j++) if(i!=j) a[i][j]=-poly(read()),a[i][i]=a[i][i]-a[i][j];else read();
ans[0]=1;
for(int i=1;i<=n;i++){
poly x=a[i][i].inv();
ans=ans*a[i][i];
for(int j=i;j<=n;j++) a[i][j]=a[i][j]*x;
for(int j=1;j<=n;j++) if(j!=i){
poly res=a[j][i];
for(int k=i;k<=n;k++) a[j][k]=a[j][k]-a[i][k]*res;
}
}
printf("%lld\n",1ll*ans[k]*mul[k]%mod);
}
}
signed main(){
star::work();
return 0;
}

P5296 [北京省选集训2019]生成树计数的更多相关文章

  1. Luogu P5296 [北京省选集训2019]生成树计数

    Luogu P5296 [北京省选集训2019]生成树计数 题目链接 题目大意:给定每条边的边权.一颗生成树的权值为边权和的\(k\)次方.求出所有生成树的权值和. 我们列出答案的式子: 设\(E\) ...

  2. 洛谷 P4002 - [清华集训2017]生成树计数(多项式)

    题面传送门 神题. 考虑将所有连通块缩成一个点,那么所有连好边的生成树在缩点之后一定是一个 \(n\) 个点的生成树.我们记 \(d_i\) 为第 \(i\) 个连通块缩完点之后的度数 \(-1\), ...

  3. Loj 2320.「清华集训 2017」生成树计数

    Loj 2320.「清华集训 2017」生成树计数 题目描述 在一个 \(s\) 个点的图中,存在 \(s-n\) 条边,使图中形成了 \(n\) 个连通块,第 \(i\) 个连通块中有 \(a_i\ ...

  4. 2019暑期金华集训 Day1 组合计数

    自闭集训 Day1 组合计数 T1 \(n\le 10\):直接暴力枚举. \(n\le 32\):meet in the middle,如果左边选了\(x\),右边选了\(y\)(且\(x+y\le ...

  5. 生成树计数 Matrix-Tree 定理 学习笔记

    一直都知道要用Matrix-Tree定理来解决生成树计数问题,但是拖到今天才来学.博主数学不好也只能跟着各位大佬博客学一下它的应用以及会做题,证明实在是不会. 推荐博客: https://www.cn ...

  6. 【BZOJ1002】【FJOI2007】轮状病毒(生成树计数)

    1002: [FJOI2007]轮状病毒 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 1766  Solved: 946[Submit][Status ...

  7. SPOJ 104 HIGH - Highways 生成树计数

    题目链接:https://vjudge.net/problem/SPOJ-HIGH 解法: 生成树计数 1.构造 基尔霍夫矩阵(又叫拉普拉斯矩阵) n阶矩阵 若u.v之间有边相连 C[u][v]=C[ ...

  8. 「UVA10766」Organising the Organisation(生成树计数)

    BUPT 2017 Summer Training (for 16) #6C 题意 n个点,完全图减去m条边,求生成树个数. 题解 注意可能会给重边. 然后就是生成树计数了. 代码 #include ...

  9. SPOJ.104.Highways([模板]Matrix Tree定理 生成树计数)

    题目链接 \(Description\) 一个国家有1~n座城市,其中一些城市之间可以修建高速公路(无自环和重边). 求有多少种方案,选择修建一些高速公路,组成一个交通网络,使得任意两座城市之间恰好只 ...

随机推荐

  1. 「题解」小 R 打怪兽 monster

    本文将同步发布于: 洛谷博客: csdn: 博客园: 简书. 题目 题目描述 小 R 最近在玩一款游戏.在游戏中,小 R 要依次打 \(n\) 个怪兽,他需要打败至少 \(k\) 个怪兽才能通关.小 ...

  2. 九、部署audit监控文件

    审计的目的是基于事先配置的规则生成日志,记录可能发生在系统上的事件(正常或非正常行为的事件),审计不会为系统提供额外的安全保护,但她会发现并记录违反安全策略的人及其对应的行为. 审计能够记录的日志内容 ...

  3. day20200911

    UG12.0进入运动仿真模块 新建仿真 定义固定连杆 定义其他连杆 定义运动副 定义驱动 定义解算方案并求解 导出动画

  4. 10个有趣又能编译为JavaScript的语言,你用过哪些?

    现代应用相比普通的网页有不同的要求.但是浏览器是一个有着一套(大部分)固定可用的技术的平台,JavaScript依然是web应用的核心语言:任何需要在浏览器上跑的应用都需要使用这种语言. 我们都知道J ...

  5. 为什么excel里面有的数据用CTRL+F,搜索搜不到?

  6. Linux命令大全之帮助命令及压缩命令

    man(manual):帮助命令 help用于解释shell内部命令 格式:help shell内部命令 ls 命令  --help man 命令 info 命令 .zip    .gz    .bz ...

  7. 注解式项目开发!详细解析Java中各个注解的作用和使用方式

    @Target 作用: 指明了修饰的这个注解的使用范围, 即被描述的注解可以用在哪里 @Target(ElementType.Type) ElementType取值的类型: TYPE: 类,接口或者枚 ...

  8. ceph-csi源码分析(6)-rbd driver-nodeserver分析(下)

    更多 ceph-csi 其他源码分析,请查看下面这篇博文:kubernetes ceph-csi分析目录导航 ceph-csi源码分析(6)-rbd driver-nodeserver分析(下) 当c ...

  9. 15 自动发布Java项目(Tomcat)

    #!/bin/bash export PAHT=/usr/local/maven/bin:/usr/local/jdk/bin:/usr/local/sbin:/usr/local/bin:/usr/ ...

  10. Linux 安装 git

    安装方法参考:http://www.jb51.net/os/RedHat/149653.html 具体内容: 在安装Git之前,需要先安装一些依赖包,安装依赖包之前可以先检查下是否已经安装. shel ...