牛客国庆集训派对Day3___H Travel —— 连通 + 组合数

题目链接:点我点我点我

题目大意:

    题目较短,但第一次理解起来可能有点绕脑。最后要求的是不同的旅游方案数,也就是不同路线选取的方案数。

解题思路:

    一开始以为是图论,想了一下好像无从下口,看了一下题解原来是有规律可循,当 m = = 1 m==1 m==1时答案为 1 1 1,当 m > 1 m>1 m>1时就可以用 m − 1 m-1 m1条边将整个图(连通的)分成 m m m个区域,恰好对应题目中的 m m m次旅游,也就是说每次旅游选取这 m m m个区域里的一个,那么很显然结果我们就要乘以这个 m m m的全排列,即旅游的顺序不同。
    然后考虑的是怎么选取这 m − 1 m-1 m1条边,就是从 n − 1 n-1 n1条边中任意选取,也就是 C ( n − 1 , m − 1 ) C(n-1,m-1) Cn1m1,求个组合数。
    最后答案即为 C ( n − 1 , m − 1 ) C(n-1,m-1) Cn1m1 ∗ * m ! m! m

代码思路:

    看到数据范围, m o d mod mod 1 e 9 + 7 1e9+7 1e9+7,用逆元求组合数即可。

核心:对题目的理解,算得上是一道读题题吧,前提是会一点数论的知识。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1 << 20;
const int mod = 1000000007;
int t, n, m, ta, tb;
ll c[maxn];
ll PowerMod(ll a, ll b, ll c) {	//快速幂 
	ll ans = 1;
	a = a % c;
	while (b>0) {
		if (b % 2 == 1)
			ans = (ans * a) % c;
		b = b / 2;
		a = (a * a) % c;
	}
	return ans;
}
void init() { //先打出阶乘,节省时间
	c[1] = 1;
	for (int i = 2; i <= maxn; i++) {
		c[i] = c[i - 1] * i%mod;
	}
}
ll C(ll n, ll m) {	//逆元求组合数 
	return c[n] * PowerMod(c[m] * c[n - m] % mod, mod - 2, mod) % mod;
}
int main(void) {
	scanf("%d", &t);
	init();
	while (t-- >0 ) {
		scanf("%d%d", &n, &m);
		for (int i = 0; i < n - 1; i++)
			scanf("%d%d",&ta,&tb);
		if (m == 1) {
			printf("1\n");
			continue;
		}
		ll ans = C(n - 1, m - 1);
		ans = (ans*c[m]) % mod;
		printf("%lld\n", ans);
	}
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值