jzoj3085-图的计数【组合数,数论】

版权声明:原创,未经作者允许禁止转载 https://blog.csdn.net/Mr_wuyongcong/article/details/86611624

正题


题目大意

求有多少个m条边的有向图使得1到n的最短路长度为n-1


解题思路

首先长度为 n 1 n-1 那么就是1到n得先是一条链。在链上加 m n + 1 m-n+1 条边且不能加如捷径边。
捷径边的条数为 C n 1 2 C_{n-1}^2 ,然后可以加的边数就是 n n C n 1 2 n*n-C_{n-1}^2 。但是考虑到有重边的情况,考虑用隔板法求。

n n C n 1 2 n*n-C_{n-1}^2 物品放入 m n + 1 m-n+1 个桶里,对于每张图就是加入桶里的第一条边,重边数量为桶中的物品数量。

然后因为 2 n 1 2\sim n-1 的点可以进行排列,所以答案要再乘上一个 ( n 2 ) ! (n-2)!

组合数用逆元求可过。


c o d e code

#include<cstdio>
#define ll long long
using namespace std;
const ll XJQ=1e9+7;
ll n,m,j[10010],z;
ll power(ll x,ll b)
{
	ll ans=1;
	x%=XJQ;
	while(b){
		if(b&1) ans=ans*x%XJQ;
		x=x*x%XJQ;b>>=1;
	}
	return ans;
}
ll C(ll n,ll m)
{
	ll ans1=1,ans2=1;
	for(ll i=n-m+1;i<=n;i++)
	  ans2=ans2*i%XJQ;
	for(ll i=1;i<=m;i++)
	  ans1=ans1*power(i,XJQ-2)%XJQ;
	return ans2*ans1%XJQ;
}
int main()
{
	scanf("%lld%lld",&n,&m);
	j[0]=1;
	for(ll i=1;i<=n-2;i++)
	  j[i]=j[i-1]*i%XJQ;
	printf("%lld",C((n*n-C(n-1,2)-1+m-n+1),m-n+1)*j[n-2]%XJQ);
}

猜你喜欢

转载自blog.csdn.net/Mr_wuyongcong/article/details/86611624