51nod 1677 treecnt 组合数

来源:互联网 发布:jsp mysql 用户注册 编辑:程序博客网 时间:2024/05/16 14:52

传送门:51nod 1677

题意:中文题。

思路:考虑结点u和其父节点v之间的边产生的贡献,设u为根节点的子树中共有sz个结点,则边对答案的贡献为:

C(n, k) - C(sz, k) - C(n - sz, k).

dfs过程中统计每一条边的贡献就好了。

代码:

#include<stdio.h>#include<bits/stdc++.h>#define ll long long#define inf 0x3f3f3f3fusing namespace std;typedef pair<int,int> P;const int MAXN = 100010;const int mod = 1e9 + 7;ll inv[MAXN], fac[MAXN];ll ans;int n, k;void init()  {      inv[0] = fac[0] = inv[1] = fac[1] = 1;      for(int i = 1; i < MAXN; i++)      fac[i] = fac[i - 1] * i % mod;      for(int i = 2; i < MAXN; i++)      inv[i] = (mod - (mod / i)) * inv[mod % i] % mod;//lucas定理求逆元      for(int i = 1; i < MAXN; i++)    inv[i] = inv[i - 1] * inv[i] % mod;   }ll C(int n, int m)//求组合数 C n,m   {  if(n < m) return 0;    return (fac[n] * inv[m] % mod) * inv[n - m] %mod;}  vector<int> mp[MAXN];int dfs(int u, int fa){int sz = 1, v;for(int i = 0; i < mp[u].size(); i++){v = mp[u][i];if(v == fa) continue;sz += dfs(v, u);}ans += (C(n, k) - C(sz, k) - C(n - sz, k));ans = (ans % mod + mod) % mod;return sz;}int main(){int u, v;init();cin >> n >> k;for(int i = 1; i < n; i++){scanf("%d %d", &u, &v);mp[u].push_back(v);mp[v].push_back(u);}dfs(1, -1);cout << ans << endl; return 0;}