题解 P7265 Look At The Sky / 加强版

题目传送门(简单版)

题目传送门(加强版)

更好的阅读体验

套路二合一……

题意简述

\(S(n)\) 为所有大小为 \(n\) 的无向图形成的集合,一张无向图的连通块集合 \(f(G)\) 为这张图所有极大连通块的大小形成的任意顺序的序列,对所有 \(k \in [0,K]\) 求:

\[s_k=\sum\limits_{G \in S(n)} \dfrac{\sum\limits_{i=1}^{|f(G)|}f(G)_i^k}{(\sum\limits_{i=1}^{|f(G)|}f(G)_i)^k} \]

\(n,k \leq 2 \times 10^5\)

题目分析

显然分母是 \(n^k\),记 \(s_k=\sum\limits_{G \in S(n)} \sum\limits_{i=1}^{|f(G)|}f(G)_i^k\)

接下来变成了求和的形式,交换和号:

\[s_k=\sum\limits_{i=1}^n i^k \sum\limits_{G \in S(n)} [i \in f(G)] \]

后面的和式与 \(k\) 无关了,记 \(f_t=\sum\limits_{G \in S(n)} [t \in f(G)]\)

\(g_t\) 为大小为 \(t\) 的无向图个数, \(h_t\) 为大小为 \(t\) 的联通无向图个数,有:

\[g_t=2^{t(t-1)/2} \]

由 exp 的组合意义(或者有标号 Set 构造),设 \(\hat H(x)\)\(\hat G(x)\) 分别为 \(h_t\)\(g_t\) 的指数型生成函数,有 \(\hat G(x)=\exp \hat H(x)\),即 \(\hat H(x)=\ln \hat G(x)\)

显然有 \(f_t= \dbinom{n}{t} h_t g_{n-t}\),即先选取 \(t\) 个点组成联通块,再用剩下的 \(n-t\) 个点组成无向图。

现在 \(f_t\) 求出来了,只需要求出 \(s_k=\sum\limits_{i=1}^n i^k f_i\)

这是一个经典问题,考虑写出 \(s_k\) 的生成函数 \(S(x)\)

\[S(x)=\sum\limits_{k} x^k \sum\limits_{i=1}^n i^kf_i=\sum\limits_{i=1}^n f_i \sum\limits_{k} (ix)^k=\sum\limits_{i=1}^n \dfrac{f_i}{1-ix} \]

直接分治 NTT 即可,总时间复杂度 \(O(n \log^2 n+k \log k)\)

为啥简单版这么卡常……

代码

......
int n,K;
int F[N],G[N],H[N];
int lenp[N],lenq[N],tmp[N];
vector <int> P[N],Q[N];
 
void init(int o,int l,int r){
	int len=r-l+1,mid=(l+r)>>1ll;
	if(o==1) len=max(n,K);
	lenp[o]=len;
	lenq[o]=len;
	P[o].resize(2*lenp[o]+2);
	Q[o].resize(2*lenq[o]+2);
	if(l==r) return ;
	init(o<<1,l,mid);
	init(o<<1|1,mid+1,r);
}
 
void solve(int o,int l,int r){
	int len=r-l+1;
	if(l==r){
		P[o][0]=F[l];
		Q[o][0]=1,Q[o][1]=(mod-l)%mod;
		return ;
	}
	int mid=(l+r)>>1;
	solve(o<<1,l,mid);
	solve(o<<1|1,mid+1,r);
	
	NTT::solve(P[o].data(),P[o<<1].data(),Q[o<<1|1].data(),lenp[o<<1],lenq[o<<1|1]);
	NTT::solve(tmp,Q[o<<1].data(),P[o<<1|1].data(),lenq[o<<1],lenp[o<<1|1]);
	for(int i=0;i<=len;i++) P[o][i]=(P[o][i]+tmp[i])%mod;
	
	NTT::solve(Q[o].data(),Q[o<<1].data(),Q[o<<1|1].data(),lenq[o<<1],lenq[o<<1|1]); 
}

int main(){
	pre();
	cin>>n>>K;
	for(int i=0;i<=n;i++) H[i]=1ll*ksm(2,S(i))*inv[i]%mod;//求出 H(x)
	poly::Ln(G,H,n);//求出 G(x)
	for(int i=0;i<=n;i++) F[i]=1ll*G[i]*mul[i]%mod*H[n-i]%mod*mul[n-i]%mod*C(n,i)%mod;//求出 F(x)
	init(1,1,n);
	solve(1,1,n);
	INV::solve(Q[1].data(),Q[1].data(),K);
	NTT::solve(P[1].data(),P[1].data(),Q[1].data(),K,K);
	for(int k=0;k<=K;k++) printf("%lld\n",1ll*P[1][k]*ksm(n,mod-1-k)%mod);
}
posted @ 2021-08-02 22:08  苹果蓝17  阅读(74)  评论(0编辑  收藏  举报