CF1109DSasha and Interesting Fact from Graph Theory(数数)

题面

传送门

前置芝士

Prufer codes与Generalized Cayley's Formula

题解

不行了脑子已经咕咕了连这么简单的数数题都不会了……

首先这两个特殊点到底是啥并没有影响,我们假设它们为(1,2)好了

首先,我们需要枚举(1,2)之间的边数(i)

我们需要考虑这中间的(i-1)个点是哪些点,而且它们的顺序对答案有影响,方案数乘上(A_{n-2}^{i-1})

(i)条边的的和要为(m),根据隔板法,方案数要乘上({m-1choose i-1})

剩下的边取值随便,方案数乘上(m^{n-1-i})

我们要把(n)个点分成(i)棵树,且如果把中间的点依次标号为(3,4,...,i+1),它们所在的树要互不相同,根据(Generalized Cayley's Formula),方案数为((i+1)n^{n-i-2})

综上,答案为

[Ans=sum_{i=1}^{n-1}A_{n-2}^{i-1}{m-1choose i-1}m^{n-1-i}(i+1)n^{n-i-2} ]

//minamoto
#include<bits/stdc++.h>
#define R register
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
using namespace std;
const int N=1e6+5,P=1e9+7;
inline int add(R int x,R int y){return x+y>=P?x+y-P:x+y;}
inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;}
inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;}
int ksm(R int x,R int y){
	R int res=1;
	for(;y;y>>=1,x=mul(x,x))(y&1)?res=mul(res,x):0;
	return res;
}
int fac[N],ifac[N],n,m,p,invn,invm,rn,rm,res;
inline int C(R int n,R int m){return 1ll*fac[n]*ifac[m]%P*ifac[n-m]%P;}
inline int A(R int n,R int m){return mul(fac[n],ifac[n-m]);}
int main(){
//	freopen("testdata.in","r",stdin);
	scanf("%d%d",&n,&m),p=max(n,m);
	fac[0]=ifac[0]=1;fp(i,1,p)fac[i]=mul(fac[i-1],i);
	ifac[p]=ksm(fac[p],P-2);fd(i,p-1,1)ifac[i]=mul(ifac[i+1],i+1);
	invn=ksm(n,P-2),invm=ksm(m,P-2),p=min(n-1,m),rn=rm=1;
	fp(i,1,n-2)rn=mul(rn,n),rm=mul(rm,m);rn=mul(rn,invn);
	fp(i,1,p)res=add(res,1ll*A(n-2,i-1)*C(m-1,i-1)%P*rn%P*rm%P*(i+1)%P),rn=mul(rn,invn),rm=mul(rm,invm);
	printf("%d
",res);
	return 0;
}
原文地址:https://www.cnblogs.com/bztMinamoto/p/10661982.html