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. AgileConfig轻量级配置中心1.3.0发布,支持多用户权限控制

    AgileConfig 当初是设计给我自己用的一个工具,所以只设置了一道管理员密码,没有用户的概念.但是很多同学在使用过后都提出了需要多用户支持的建议.整个团队或者整个公司都使用同一个密码来管理非常的 ...

  2. 从 Nginx 优秀的核心架构设计,揭秘其为何能支持高并发?

    目录: 1. Nginx的整体架构 2. Nginx的模块化设计 3. Nginx的请求方式处理 4. Nginx事件驱动模型 5. Nginx进程处理模型 写在前面 Nginx 是一个 免费的,开源 ...

  3. c 语言学习第一天

    编辑器:Dev-C++ 变量命名(标识符) 变量名只能是英文字母[A-Z,a-z]和数字[0-9]或者下划线[_]组成. 第一个字母必须是字母或者下划线开头. 变量名区分大小写.例如:Fish≠fis ...

  4. vs联合halcon——采集图像(实时采集与单次采集)

    摘要 在对vs进行环境配置好以后,就可以开始与halcon联合进行实战.本篇就对图像的采集进行总结.通过构建采集相机GrabImage类的三个方法实现图像的采集: open() 打开相机 grabim ...

  5. 番外篇:使用nssm工具将ES、Kibana、Logstash或者其他.bat文件部署为Windows后台服务的方法

    使用NSSM工具安装bat文件为Windows服务 nssm是一个可以把bat批处理文件部署为Windows服务的小工具.例如很多.net项目可能还是在Windows服务器上面跑的,但是很多组件只提供 ...

  6. 第6章:深入理解Pod对象

    Pod是最小的部署单元,也是后面经常配置的地方,本章节带你熟悉Pod中常见资源配置及参数. 也就是YAML这部分: ... template: metadata: labels: app: web s ...

  7. 通过xrdp连接centos7桌面:

    6.1.需求场景: 1.希望使用windows远程访问centos图形界面,使用xmanager连接centos远程桌面时有以下问题: (1)只能有一个用户同时使用xmanger连接远程桌面,多个用户 ...

  8. WinUI桌面版替换UWP项目实际使用

    最近做了一个3D打印的RC遥控车.然后就想着用xbox手柄控制小车的前进和转向吧,于是就用surface平板接收收手柄的数据,然后通过串口的2.4G模块传输数据,看上挺简单的,其实本身也挺简单的. 我 ...

  9. Linux云计算-04_Linux用户及权限管理

    Linux是一个多用户的操作系统,引入用户,可以更加方便管理Linux服务器,系统默认需要以一个用户的身份登录,而且在系统上启动进程也需要以一个用户身份器运行,用户可以限制某些进程对特定资源的权限控制 ...

  10. MongoDB数据库 5分钟快速上手

    安装 本次安装使用docker镜像,安装无障碍,一行命令即可解决 # 安装镜像并启动 可以自行修改命令中的参数 ## 账户 tanoak 密码 123123 ## -p 27018:27017 映射端 ...