传送门

题意:定义一个无向图的权值为图中形为树的连通块数量的$k$次方,求所有$n$个点有标号的简单无向图的权值之和。

这个题还是很妙的啊……(好吧,其实只有最后的复合函数求导比较有意思……)

先套路一发,定义答案的$EGF$为$F(x)$一棵树的$EGF$为$T(x)$,每个连通块都不是树的$EGF$为$G(x)$,强制连通的无向图的$EGF$为$H(x)$,显然有

\begin{align}F(x)=\left(\sum_{i\ge 0}\frac{i^k T(x)^i}{i!}\right)G(x)\end{align}

意思就是枚举树的数量,统计数量之后乘上贡献,左边要除以$i!$是为了去重(因为几个树组成的图是集合,不是序列,元素没有顺序)。

根据一些简单的知识不难得到以下结论:

$[x^n]T(x)=n^{n-2}$

$G(x)=\exp(H(x)-T(x))$(因为每个连通块都不能是树,那么我们用连通图个数减掉树的个数,再用这个东西搞一个集合即可,不难发现就是对一个连通块的$EGF$做一下$\exp$的结果。)

$H(x)$可以跑多项式$\ln$之类的东西得到(参见城市规划的做法),那么后面的$G(x)$就好算了,然后再解决前面的那个东西就可以$O(n)$得出最后的答案了(因为只要求一项,所以暴力求出卷积的第$n$项即可)。

定义

\begin{align}A_k(x)=\sum_{i\ge 0}\frac{i^k T(x)^i}{i!}\end{align}

注意到$A_k(x)$其实是一个复合函数,那么假设有$f(T)=A_k(x)$,我们可以尝试对$f(T)$求个导,而根据复合函数求导法则($(f(g(x)))’=f’(g(x))g’(x)$)有$[T^i]f’(T)=\frac{i^k T(x)^{i-1}T'(x)i}{i!}=T'(x)\frac{i^{k+1}T(x)^{i-1}}{i!}$,因此$[T^i]f’(T)=\frac{i^k T(x)^{i-1}T'(x)i}{i!}=T'(x)\frac{i^{k+1}T(x)^{i-1}}{i!}$。

因为$f(T)$本质就是$A_k(x)$,因此$f’(T)$和$A_k’(x)$是等价的,所以有

\begin{align}A_k'(x)=\frac{T'(x)}{T(x)}\sum_{i\ge 1}\frac{i^{k+1}T(x)^i}{i!}=\frac{T'(x)}{T(x)}A_{k+1}(x)\end{align}

(注意这里不用处理常数项的问题,因为$k>0$时有$[x^0]A_k(x)=0$)

也就是说$A_{k+1}(x)=A_k'(x)\frac{T(x)}{T'(x)}$,那么直接利用这个递推$k$次即可,边界也不难得到:

\begin{align}A_0(x)=\sum_{i\ge 0}\frac{i^0 T(x)^i}{i!}=\exp(T(x))\end{align}

然后就可以做了,复杂度$O(kn\log n)$,因为$\exp$只需要做两次,所以常数还是不大的。

(虽然比起NTT优化DP的做法来说代码长还跑得慢……)

 #include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=,p=,g=;
void NTT(int*,int,int);
void getexp(int*,int*,int);
void getln(int*,int*,int);
void getinv(int*,int*,int);
void getderivative(int*,int*,int);
void getintegrate(int*,int*,int);
int qpow(int,int,int);
int n,N=,k,A[maxn],B[maxn],C[maxn],T[maxn],G[maxn],fac[maxn],fac_inv[maxn],inv[maxn],ans=;
int main(){
scanf("%d%d",&n,&k);
while(N<=n)N<<=;
fac[]=fac_inv[]=;
for(int i=;i<N;i++)fac[i]=(long long)fac[i-]*i%p;
fac_inv[N-]=qpow(fac[N-],p-,p);
for(int i=N-;i;i--)fac_inv[i]=(long long)fac_inv[i+]*(i+)%p;
for(int i=;i<N;i++)inv[i]=(long long)fac_inv[i]*fac[i-]%p;
T[]=G[]=;
for(int i=;i<=n;i++)T[i]=(long long)qpow(i,i-,p)*fac_inv[i]%p;
for(int i=;i<=n;i++)G[i]=(long long)qpow(,(((long long)i*(i-))>>)%(p-),p)*fac_inv[i]%p;
getln(G,B,N);
for(int i=;i<N;i++)B[i]=(B[i]-T[i]+p)%p;
getexp(B,G,N);
fill(B,B+(N<<),);
getderivative(T,B,N);
getinv(B,C,N);
copy(T,T+N,B);
NTT(B,N<<,);
NTT(C,N<<,);
for(int i=;i<(N<<);i++)C[i]=(long long)B[i]*C[i]%p;
NTT(C,N<<,-);
fill(C+N,C+(N<<),);
NTT(C,N<<,);
getexp(T,A,N);
for(int j=;j<=k;j++){
fill(B,B+(N<<),);
getderivative(A,B,N);
NTT(B,N<<,);
for(int i=;i<(N<<);i++)B[i]=(long long)B[i]*C[i]%p;
NTT(B,N<<,-);
copy(B,B+N,A);
}
for(int i=;i<=n;i++)ans=(ans+(long long)A[i]*G[n-i]%p)%p;
printf("%d",(int)((long long)ans*fac[n]%p));
return ;
}
void NTT(int *A,int n,int tp){
for(int i=,j=,k;i<n-;i++){
k=n;
do j^=(k>>=);while(j<k);
if(i<j)swap(A[i],A[j]);
}
for(int k=;k<=n;k<<=){
int wn=qpow(g,(tp>?(p-)/k:(p-)/k*(long long)(p-)%(p-)),p);
for(int i=;i<n;i+=k){
int w=;
for(int j=;j<(k>>);j++,w=(long long)w*wn%p){
int a=A[i+j],b=(long long)w*A[i+j+(k>>)]%p;
A[i+j]=(a+b)%p;
A[i+j+(k>>)]=(a-b+p)%p;
}
}
}
if(tp<){
int inv=qpow(n,p-,p);
for(int i=;i<n;i++)A[i]=(long long)A[i]*inv%p;
}
}
void getexp(int *A,int *C,int n){
static int B[maxn];
fill(C,C+(n<<),);
C[]=;
for(int k=;k<=n;k<<=){
getln(C,B,k);
for(int i=;i<k;i++)B[i]=(A[i]-B[i]+p)%p;
B[]=(B[]+)%p;
NTT(B,k<<,);
NTT(C,k<<,);
for(int i=;i<(k<<);i++)C[i]=(long long)B[i]*C[i]%p;
NTT(C,k<<,-);
fill(C+k,C+(k<<),);
}
}
void getln(int *A,int *C,int n){
static int B[maxn];
getderivative(A,B,n);
fill(B+n,B+(n<<),);
getinv(A,C,n);
NTT(B,n<<,);
NTT(C,n<<,);
for(int i=;i<(n<<);i++)B[i]=(long long)B[i]*C[i]%p;
NTT(B,n<<,-);
getintegrate(B,C,n);
fill(C+n,C+(n<<),);
}
void getinv(int *A,int *C,int n){
static int B[maxn];
fill(C,C+(n<<),);
C[]=qpow(A[],p-,p);
for(int k=;k<=n;k<<=){
copy(A,A+k,B);
fill(B+k,B+(k<<),);
NTT(B,k<<,);
NTT(C,k<<,);
for(int i=;i<(k<<);i++)C[i]=C[i]*((-(long long)C[i]*B[i]%p+p)%p)%p;
NTT(C,k<<,-);
fill(C+k,C+(k<<),);
}
}
void getderivative(int *A,int *C,int n){
for(int i=;i<n;i++)C[i-]=(long long)A[i]*i%p;
C[n-]=;
}
void getintegrate(int *A,int *C,int n){
for(int i=;i<n;i++)C[i]=(long long)A[i-]*inv[i]%p;
C[]=;
}
int qpow(int a,int b,int p){
int ans=;
for(;b;b>>=,a=(long long)a*a%p)if(b&)ans=(long long)ans*a%p;
return ans;
}

ps:代码里把每次乘的$\frac{T(x)}{T’(x)}$算出来之后直接存它的$DFT$了,这样每次乘的时候就只需要对$A_k(x)$做$DFT$和$IDFT$了,可以减小很多常数。

这个题给我的两点启发:

1.看见跟前面那半类似的式子就去试试求导和积分

2.牢记复合函数求导法则(论不学文化课的危害……)

hdu5824 graph的更多相关文章

  1. [开发笔记] Graph Databases on developing

    TimeWall is a graph databases github It be used to apply mathematic model and social network with gr ...

  2. Introduction to graph theory 图论/脑网络基础

    Source: Connected Brain Figure above: Bullmore E, Sporns O. Complex brain networks: graph theoretica ...

  3. POJ 2125 Destroying the Graph 二分图最小点权覆盖

    Destroying The Graph Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 8198   Accepted: 2 ...

  4. [LeetCode] Number of Connected Components in an Undirected Graph 无向图中的连通区域的个数

    Given n nodes labeled from 0 to n - 1 and a list of undirected edges (each edge is a pair of nodes), ...

  5. [LeetCode] Graph Valid Tree 图验证树

    Given n nodes labeled from 0 to n - 1 and a list of undirected edges (each edge is a pair of nodes), ...

  6. [LeetCode] Clone Graph 无向图的复制

    Clone an undirected graph. Each node in the graph contains a label and a list of its neighbors. OJ's ...

  7. 讲座:Influence maximization on big social graph

    Influence maximization on big social graph Fanju PPT链接: social influence booming of online social ne ...

  8. zabbix利用api批量添加item,并且批量配置添加graph

    关于zabbix的API见,zabbixAPI 1item批量添加 我是根据我这边的具体情况来做的,本来想在模板里面添加item,但是看了看API不支持,只是支持在host里面添加,所以我先在一个ho ...

  9. Theano Graph Structure

    Graph Structure Graph Definition theano's symbolic mathematical computation, which is composed of: A ...

随机推荐

  1. Laravel 的核心概念

    工欲善其事,必先利其器.在开发Xblog的过程中,稍微领悟了一点Laravel的思想.确实如此,这篇文章读完你可能并不能从无到有写出一个博客,但知道Laravel的核心概念之后,当你再次写起Larav ...

  2. RN 47 初始化 Bridge 过程

    - (instancetype)initWithDelegate:(id<RCTBridgeDelegate>)delegate bundleURL:(NSURL *)bundleURL ...

  3. json 模块的基本使用学习

    内容大纲 1: 为什么要学习json模块 >1:因为网络之间的通信,还有不同语言之间的相互内容沟通,需要用到json 模式进行沟通 >2:写入部分文件用json文件保存, 2:json的序 ...

  4. python基础知识梳理-----7函数

    基本内容梳理 1:函数定义,函数名,函数体以及函数的调用方式 2:函数的返回值 3:函数的参数 4:函数---动态传参数 5:名称空间,局部名称的加载顺序,全局名称空间,作用域,加载顺序 6:函数的嵌 ...

  5. SAE实践——用SVN命令行同步/提交代码

    1. 同步应用到本地 注:首次使用svn需要输入安全认证密码 在终端输入以下命令 svn co https://svn.sinaapp.com/nyhello nyhello替换为自己的应用名称. 用 ...

  6. 关于Hibernate的一个简单小程序

    本人根据视频学习了一下三大框架中比较简单的一个Hibernate,并简单完成了一个运用Hibernate的小程序 Hibernate是一个简化web程序Dao层的一个框架,应用他,可以完全脱离sql语 ...

  7. Java实现BF算法

    package 串的算法; public class BF { public static void main(String[] args) { String a = "aaabbaaacc ...

  8. Mac OS 10.12使用SecureCRT 8.1.4无法保存密码的问题解决

    参考上图取消Use Keychain即可. 参考: https://jingyan.baidu.com/article/915fc414fda5fb51394b20bd.html

  9. Hive的Shell里hive> 执行操作时,出现FAILED: Execution Error, return code 1 from org.apache.hadoop.hive.ql.exec.DDLTask错误的解决办法(图文详解)

    不多说,直接上干货! 这个问题,得非 你的hive和hbase是不是同样都是CDH版本,还是一个是apache版本,一个是CDH版本. 问题详情 [kfk@bigdata-pro01 apache-h ...

  10. Linux网络编程--多线程实现echo服务器与客户端“一对多”功能,是网络编程的“Hello World!”

    在linux平台下,用多线程实现echo服务器与客户端“一对多”(即是一台服务器可以响应多个客户端的请求).本人写了个demo,和大家一起分享,有不足的地方,请多多指教,我是壮壮熊. 编译时,在后面加 ...