树
https://ac.nowcoder.com/acm/problem/13611
https://ac.nowcoder.com/discuss/401225
题目描述
shy有一颗树,树有
n
n
n 个结点。有
k
k
k 种不同颜色的染料给树染色。一个染色方案是合法的,当且仅当对于所有相同颜色的点对
(
x
,
y
)
(x,y)
(x,y),
x
x
x 到
y
y
y 的路径上的所有点的颜色都要与
x
x
x 和
y
y
y 相同。请统计方案数。
输入描述:
第一行两个整数
n
n
n,
k
k
k 代表点数和颜色数;
接下来
n
−
1
n-1
n−1 行,每行两个整数
x
,
y
x,y
x,y 表示
x
x
x 与
y
y
y 之间存在一条边;
输出描述:
输出一个整数表示方案数
(
m
o
d
1
e
9
+
7
)
(mod \ 1e9+7)
(mod 1e9+7)。
示例1
输入
4 3
1 2
2 3
2 4
输出
39
备注:
对于
30
%
30\%
30% 的数据,
n
≤
10
,
k
≤
3
n≤10, k≤3
n≤10,k≤3;
对于
100
%
100\%
100% 的数据,
n
,
k
≤
300
n,k≤300
n,k≤300。
思路:
这道题可以转化成一道排列组合的问题,将这棵树分成不超过
k
k
k 个连通块,每个连通块图涂不同的颜色。若将一棵树分成
i
i
i 个连通块,那么要删去
i
−
1
i-1
i−1 条边,方案数为
C
n
−
1
i
−
1
\mathrm{C}_{n-1}^{i-1}
Cn−1i−1,然后从
k
k
k 种颜色中选
i
i
i 种染色,方案数为
A
k
i
\mathrm{A}_{k}^{i}
Aki。
所以,总的方案数就是
∑
i
=
1
m
i
n
(
n
,
k
)
C
n
−
1
i
−
1
A
k
i
\sum_{i = 1}^{min(n,k)}\mathrm{C}_{n-1}^{i-1}\mathrm{A}_{k}^{i}
∑i=1min(n,k)Cn−1i−1Aki。
Code:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod = 1e9 + 7;
const int N = 310;
ll n, k, ans, fac[N], inv[N];
ll C(ll a, ll b) {
return fac[a] * inv[b] % mod * inv[a - b] % mod;
}
ll A(ll a, ll b) {
return fac[a] * inv[a - b] % mod;
}
int main() {
ios::sync_with_stdio(false);
cin >> n >> k;
inv[0] = inv[1] = fac[0] = fac[1] = 1;
for (ll i = 2; i <= max(n, k); i++) {
inv[i] = (mod - mod / i) * inv[mod % i] % mod; //公式递推求 i 的逆元
}
for (ll i = 2; i <= max(n, k); i++) {
fac[i] = fac[i - 1] * i % mod;
inv[i] = inv[i] * inv[i - 1] % mod;
}
for (ll i = 1; i <= min(n, k); i++) {
ans = (ans + C(n - 1, i - 1) * A(k, i) % mod) % mod;
}
cout << ans << endl;
return 0;
}
Code2:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod = 1e9 + 7;
const int N = 310;
ll n, k, ans, fac[N];
ll qpow(ll a, ll b) {
ll res = 1;
while (b) {
if (b & 1) res = res * a % mod;
a = a * a % mod;
b >>= 1;
}
return res % mod;
}
ll Inv(ll a, ll p) {
return qpow(a, p - 2);
}
ll C(ll a, ll b) {
return fac[a] * Inv(fac[b], mod) % mod * Inv(fac[a - b], mod) % mod;
}
ll A(ll a, ll b) {
return fac[a] * Inv(fac[a - b], mod) % mod;
}
int main() {
ios::sync_with_stdio(false);
cin >> n >> k;
fac[0] = 1;
for (ll i = 1; i <= max(n, k); i++) {
fac[i] = fac[i - 1] * i % mod;
}
for (ll i = 1; i <= min(n, k); i++) {
ans = (ans + C(n - 1, i - 1) * A(k, i) % mod) % mod;
}
cout << ans << endl;
return 0;
}