【数学 图论】JZOJ_3085 图的计数

题意

询问有多少个 N N N个点, M M M条边的有向图,从 1 1 1号点到达 N N N号点需要经过至少 N − 1 N-1 N1条边。该有向图中可以包含重边和自环。方案数 % 1000000009 \%1000000009 %1000000009

思路

因为至少是 N − 1 N-1 N1条边,所以这构成了一条链,我们要在这链里加边且不是捷径边。

一共可以加入 N 2 N^2 N2条边,捷径边的边数有 C N − 1 2 C_{N-1}^{2} CN12条边,那么还能加进去的边还有 N 2 − C N − 1 2 N^2-C_{N-1}^{2} N2CN12

因为图中有 M M M条边,用了 N − 1 N-1 N1条边,所以还剩 M − N + 1 M-N+1 MN+1条边,我们要把这能加进的 N 2 − C N − 1 2 N^2-C_{N-1}^{2} N2CN12边放到这里面。

这里给出一个公式,把 N N N个相同的元素放进 M M M个桶的方案数为 C N + M − 1 N C_{N+M-1}^{N} CN+M1N

然后我们就可以套公式求出答案了,然后取模就直接算逆元。

代码

#include<cstdio>

const int P = 1e9 + 7;
int n, m;
int fact[10001];

int power(int a, int b) {
	int result = 1;
	a %= P;
	for (; b; b >>= 1) {
		if (b & 1) result = (long long)result * a % P;
		a = (long long)a * a % P;
	}
	return result;
}

long long C(int n, int m) {
	long long a = 1, b = 1;
	for (int i = n; i > n - m; i--)
		a = a * i % P;
	for (int i = 1; i <= m; i++)
		b = b * power(i, P - 2) % P;
	return a * b % P;
}

int main() {
	scanf("%d %d", &n, &m);
	fact[0] = 1;
	for (int i = 1; i <= n - 2; i++)
		fact[i] = (long long)fact[i - 1] * i % P;
	printf("%d", C(n * n - C(n - 1, 2) - 1 + m - n + 1, m - n + 1) * fact[n - 2] % P);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值