传送门

题意:定义一个无向图的权值为图中形为树的连通块数量的$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. python 之 比较哪个数据大小

    #定义一个字典info={}#定义比较的人数n=int(input("请输入你要比较的人数"))#循环while(n): #输入a,b 两个数据 ,分别代表学号 和分数 # 把输入 ...

  2. Linux之E: 无法锁定管理目录(/var/lib/dpkg/),是否有其他进程正占用它?

    解决 ubantu系统中 E: 无法锁定管理目录(/var/lib/dpkg/),是否有其他进程正占用它? 的 问题. 1.解决办法: 当我们有的时候在使用apt-get install/update ...

  3. python3.6使用scrapy报错

    用python做爬虫的,肯定熟悉scrapy,不过新手安装总是会遇到各种奇葩错误. 错误一:building 'twisted.test.raiser' extensionerror: Microso ...

  4. 解压命令tar zxvf中zxvf的意思

    x : 从 tar 包中把文件提取出来 z : 表示 tar 包是被 gzip 压缩过的,所以解压时需要用 gunzip 解压 v : 显示详细信息 f xxx.tar.gz : 指定被处理的文件是 ...

  5. GoLand 调试 Go

    Goland 调试 Go 从百度得知 VS Code 不能很好的支持 Go 的调试真让人肝儿疼 -- 引言 准备 Win 10 Pro Go(Version 1.10) GoLand(2018.3) ...

  6. Linux网络编程服务器模型选择之IO复用循环并发服务器

    在前面我们介绍了循环服务器,并发服务器模型.简单的循环服务器每次只能处理一个请求,即处理的请求是串行的,效率过低:并发服务器可以通过创建多个进程或者是线程来并发的处理多个请求.但是当客户端增加时,就需 ...

  7. 【Eclipse】在Project Explore中隐藏不需要显示的文件

    右击项目->Resource->Resource Filters->AddFilter type: Exclude allApplies to : Files (All childr ...

  8. Android进程管理

    1.进程按照优先级分为不同的等级FVSBE Foreground process前台进程:用户可看到进程里某个activity界面(可以获得焦点的) Visible process可见进程:用户仍可见 ...

  9. c++面试题中经常被面试官面试的小问题总结(二)(本篇偏向指针知识)

    原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/10713204.html 1.利用指针交换两个字符串方法?(这题是我当年读大一的时候看到的,好怀 ...

  10. mock时忽略不必要的初始化

    PowerMockito.mockStatic时忽略加载类的静态field,比如想PowerMockito.mockStatic(ClassA.class),ClassA如下 public class ...