NC13611 - 树

题目链接

思路:一棵树,从一个点到另一个点只有一条路,这样经过的点就不会存在于其他路径上,所以这个题目其实就是让我们求,n个点,分成 i(1~n)份,每一份可以从k种染料中选一个进行染色,问有多少种方案。能想到是数论题就已经成功一半了。

先看可以有多少种分法:分成两份就需要砍一个边,三份两个边,n个点就有n-1条边,砍成i份就需要砍 i-1 个边,三个点分成两份,有多少种分法?1为根节点: 12 3; 13 2 吧,这个公式应该就呼之欲出了:n个点分成i份有多少种分法: C n − 1 i − 1 C_{n-1}^{i-1} Cn1i1

再看有k种染料,需要给i堆节点染色,有多少种染法?有顺序要求的话: A k i A_{k}^{i} Aki

所以题目要求的是以上两个步骤同时满足就需要相乘嘛:n个点分成 i 份,每份需要从k种染料中选择一种染色 有多少种情况? C n − 1 i − 1 ∗ A k i C_{n-1}^{i-1}*A_{k}^{i} Cn1i1Aki 那么 i 是由 1~n 的,但是 n 比 k 大的情况,这时候在i 也比 k大的时候 染料就不够分了,所以遍历就需要 1 ~ min(n,k) 就好了 公式就是 ∑ i = 1 m i n ( n , k ) C n − 1 i − 1 ∗ A k i \sum_{i=1}^{min(n,k)}C_{n-1}^{i-1}*A_{k}^{i} i=1min(n,k)Cn1i1Aki

因为这个公式里面会涉及除法,并且需要取模,需要用一下逆元。

#include <bits/stdc++.h>
using namespace std;
const int mod = 1e9+7;
int n, k;
long long pre[305];

long long qpow(long long x, long long n) { 
	long long res = 1; 
	for (; n; n >>= 1, x = x * x % mod) 
		if (n & 1) res = res * x % mod; 
	return res; 
}

long long C(long long x, long long y) {
	return pre[x] * qpow(pre[y]*pre[x-y]%mod, mod-2) % mod;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值