简单子环图 题解

简单子环图 题解

题意

\(~~~~\) 求有多少 \(n\) 个点 \(m\) 条边的有标号无向图是一个环的子图。

\(~~~~\) \(1\leq n,m\leq 10^5\).

题解

\(~~~~\) 比较中规中矩的一道题,但输在了非生成函数部分,记录一下。

\(~~~~\) 显然图的形态应该是若干条链,所以我们考虑连通块。显然 \(n\) 个点 \(m\) 条边有 \(n-m\) 个连通块。(下文记其为 \(k\) )设划分出的连通块大小分别为 \(Siz_1,Siz_2,\dots,Siz_k\) ,那么显然划分进连通块的方案数就是:

\[\dfrac{n!}{\prod_{i=1}^n Siz_i!} \]

\(~~~~\) (把连通块视作颜色比较好想)

\(~~~~\) 然后假设大小为 \(i\) 的连通块的连边方案为 \(p_i\) ,则:

\[ p_i= \left\{\begin{array}{l} 1~~~~ i=1\\ \dfrac{i!}{2} ~~~~ \text{Otherwise.} \end{array}\right. \]

\(~~~~\) 对我就是输在了这里(

\(~~~~\) 所以我们可以写出最后的答案:

\[\dfrac{n! \prod p_i}{\prod_{i=1}^n Siz_i!\times k!} \]

\(~~~~\) 常数提出来,利用 \(\sum Siz=n\) 自然地构造生成函数:

\[F(x)=\dfrac{p_i}{i!}x^i \]

\(~~~~\)\(p_i\) 代进去,它的数列应该是:\(x+\sum_{i=2}^\infty \dfrac{1}{2}x^i\)

\(~~~~\) 后面部分的封闭形式众所周知,所以是 \(x+x^2\dfrac{\frac{1}{2}}{1-x}=\dfrac{x}{1-x}(1-\dfrac{1}{2}x)\)

\(~~~~\)\(k\) 个连通块,所以卷 \(m\) 次,自然而然地打开,得到 \(x^n\) 项系数为:

\[\sum_{i=0}^k \begin{pmatrix} k\\i \end{pmatrix}\times (-\dfrac{1}{2})^i\times \begin{pmatrix} i+k-1\\k-1 \end{pmatrix} \]

\(~~~~\) 代入,然后再乘上上面分离的常数即可。

代码

#include <cstdio>
#include <algorithm>
#define ll long long
using namespace std;
const ll MOD=1e9+7;
inline ll Add(ll a,ll b){return (1ll*a+b)%MOD;}
inline ll Dec(ll a,ll b){return (1ll*a-b+MOD)%MOD;}
inline ll Mul(ll a,ll b){return 1ll*a*b%MOD;}
ll qpow(ll a,ll b)
{
	ll ret=1;
	while(b)
	{
		if(b&1) ret=Mul(ret,a);
		b>>=1;a=Mul(a,a); 
	}
	return ret;
}
const ll Inv2=qpow(2,MOD-2);
ll Fac[100005],Inv[100005],Pow[100005];
inline ll C(ll n,ll r){if(n<r) return 0;return Mul(Fac[n],Mul(Inv[r],Inv[n-r]));}
int main() {
	ll T,n,m;
	Fac[0]=Pow[0]=1;
	for(ll i=1;i<=100000;i++) Fac[i]=Mul(Fac[i-1],i),Pow[i]=Mul(Pow[i-1],Dec(MOD,Inv2));
	Inv[100000]=qpow(Fac[100000],MOD-2);
	for(ll i=99999;i>=0;i--) Inv[i]=Mul(Inv[i+1],i+1);
	scanf("%lld",&T);
	while(T--)
	{
		scanf("%lld %lld",&n,&m);
		if(n==m) {printf("%lld\n",Mul(Fac[n-1],Inv2));continue;}
		if(n<m) {printf("0\n");continue;} 
		ll k=n-m,Ans=0;
		for(ll i=0;i<=k;i++)
			Ans=Add(Ans,Mul(C(k,i),Mul(Pow[i],C(n-i-1,k-1))));
		printf("%lld\n",Mul(Ans,Mul(Fac[n],Inv[k])));
	}
	return 0;
}
posted @ 2022-07-12 22:36  Azazеl  阅读(65)  评论(0)    收藏  举报