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. Python-selenium,切换句柄及封装

    一.获取当前句柄及所有句柄 handle=driver.current_window_handle #获取当前窗口句柄print(handle)handles=driver.window_handle ...

  2. springboot——重定向解决刷新浏览器造成表单重复提交的问题(超详细)

    原因:造成表单重复提交的原因是当我们刷新浏览器的时候,浏览器会发送上一次提交的请求.由于上一次提交的请求方式为post,刷新浏览器就会重新发送这个post请求,造成表单重复提交. 解决办法: 将请求当 ...

  3. Task02:基础查询与排序

    2.1 SELECT语句基础 2.1.1 从表中选取数据 SELECT语句 从表中选取数据时需要使用SELECT语句,也就是只从表中选出(SELECT)必要数据的意思.通过SELECT语句查询并选取出 ...

  4. MySQL:如何使用MyCAT实现分库分表?

    分库分表介绍 随着微服务这种架构的兴起,我们应用从一个完整的大的应用,切分为很多可以独立提供服务的小应用.每个应用都有独立的数据库. 数据的切分分为两种: 垂直切分:按照业务模块进行切分,将不同模块的 ...

  5. 基于websocket vue 聊天demo 解决方案

    基于websocket vue 聊天demo 解决方案 demo 背景 电商后台管理的客服 相关技术 vuex axios vue websocket 聊天几种模型 一对一模型 一对一 消息只一个客户 ...

  6. Oracle简单分析

    1.Oracle 数据库是甲骨文公司开发的一种关系型数据库管理系统,也就是RDBMS(relational database management system). 2.Oracle 从头到尾都是一个 ...

  7. centos7安装JDK、CentOS

    1.安装JDK 1.1查看系统是否已有自带的JDK rpm -qa |grep java rpm -qa |grep jdk rpm -qa |grep gcj 1.2卸载已有安装 如果没有输出信息, ...

  8. .NET Core/.NET5/.NET6 开源项目汇总8:Blazor项目

    系列目录     [已更新最新开发文章,点击查看详细] Blazor 是一个使用 .NET 生成交互式客户端 Web UI 的框架: 使用 C# 代替 JavaScript 来创建信息丰富的交互式 U ...

  9. 看CarbonData如何用四招助力Apache Spark

    摘要:CarbonData 在 Apache Spark 和存储系统之间起到中介服务的作用,为 Spark 提供的4个重要功能. 本文分享自华为云社区<Make Apache Spark bet ...

  10. 最多能创建多少个 TCP 连接?

    我是一个 Linux 服务器上的进程,名叫小进. 老是有人说我最多只能创建 65535 个 TCP 连接. 我不信这个邪,今天我要亲自去实践一下. 我走到操作系统老大的跟前,说: "老操,我 ...