【每日一题】树

https://ac.nowcoder.com/acm/problem/13611

首先思考一下,题目需要你将一棵树分成若干个连通块,连通块上的颜色相同,不同连通块之间的颜色不同。
然后数据范围很小,考虑树上dp,dp[i][j] 表示第 i 个节点为根的子树分成 j 个连通块的方案数。

然后我就不会了,但是仔细一想,把一棵树分成两个连通块不就是删除一条边,那分成 x 个连通块不就是选择 x-1 条边删除,然后在颜色里面选 x 种颜色给涂上去。这就是一个简单的组合数学问题。

如果把树分成 x 个连通块,那么就要选择 x-1 条边,也就是有 种方案,对于每一种分连通块的方案,可以有 种取颜色的方案,最后把颜色涂上去有 x 的全排列种也就是 种方案,那么把树分成 x 个连通块的答案 。而最终答案就是连通块个数 ,复杂度

其实这道题可以数据范围可以出到 的。

#include <bits/stdc++.h>
using namespace std;
static auto faster_iostream = []() { ios::sync_with_stdio(0); cin.tie(0); return 0; }();
typedef long long ll;
const int N = 1e3 + 5, M = 1e9 + 7;
ll qpow(ll x, ll n) { ll res = 1; for (; n; n >>= 1, x = x * x % M) if (n & 1) res = res * x % M; return res; }

ll fac[N];

ll comb(ll n, ll m) {
  return fac[n] * qpow(fac[m] * fac[n-m] % M, M - 2) % M;
}

int main() {
  int n, k;
  cin >> n >> k;

  fac[0] = fac[1] = 1;
  for (int i = 2; i <= max(n, k); i++) {
    fac[i] = fac[i-1] * i % M;
  }
  ll ans = 0;
  for (int i = 0; i <= min(n - 1, k - 1); i++) {
    ans += comb(n - 1, i) * comb(k, i + 1) % M * fac[i + 1] % M;
    ans %= M;
  }
  cout << ans << '\n';
}
全部评论
知道为什么不到1e6吗?因为数据不好造
点赞 回复 分享
发布于 2020-04-06 14:18
这个思路很强啊!
点赞 回复 分享
发布于 2020-04-07 10:01
哇太强啦大神!
点赞 回复 分享
发布于 2020-04-12 17:48

相关推荐

Boss上联系了很多都已读不回,是什么问题大佬帮看看
扎哇精神病人:老哥 你本科的时间是不是写错了
点赞 评论 收藏
分享
02-16 13:52
门头沟学院 Java
给🐭🐭个面试机会吧:嘿,mvbatis
点赞 评论 收藏
分享
牛客245670684号:虚拟货币预测正确率百分之99,还要找工作干嘛,不早就财富自由了
点赞 评论 收藏
分享
评论
8
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务