题意:给你n个结点,n-1条边,要从这n个结点里面选出k个结点,再选出最少边使这些结点之间相互连通,问对于所有选择k个结点的最小选择边数的总和是多少。

题解:因为每次选k个点其实是固定了的,所以撇开要确定的边,每次要选的k个点就是一个组合数问题,那怎么把点和边联系起来呢?对于任意一条边,它要不要被选入作为连接点的边是由它两边的点决定的。当只有这条边左边或者右边的点被选入时,这条边是不需要的,只有当两端的两个点同时被选入,这条边才会对答案有贡献。

而判断这条边两端的点被选入的情况时,只用分三种情况:

① 在这条边左边选了k个点,这条边不计入答案,无贡献。

② 在这条边右边选了k个点,这条边不计入答案,无贡献。

③ 在这条边两端都选了点,这条边必然记入答案,贡献加1。

所以根据上面的情况我们容易得到 对于每一条边它的贡献是:ans=C(n,k)-C(t,k)-C(n-t,k),这里的t就是该边左边的结点数。已经知道这个式子了,我们只需要统计每条边左边和右边的结点总数,然后依次带入式子把答案求出来就行了。由于题目要求取模,阶乘的数又比较大所以要用到阶乘逆元(套个阶乘逆元的板子就行了)。

附上代码:

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const ll mod=1e9+7;
const ll maxn=1000010;

ll fac[maxn]; //阶乘
ll inv[maxn];//阶乘的逆元
ll n,k,ans,ss;
vector<ll>q[maxn];
ll qpow(ll x,ll n)
{
    ll ret=1;
    for(; n; n>>=1)
    {
        if(n&1)
            ret=ret*x%mod;
        x=x*x%mod;
    }
    return ret;
}
void getjni()
{
    fac[1]=1;
    for(int i=2; i<=maxn; i++)//预处理阶乘
        fac[i]=fac[i-1]*i%mod;
    inv[maxn]=qpow(fac[maxn],mod-2);//求阶乘的逆元
    for(int i=maxn-1; i>=0; i--)
        inv[i]=inv[i+1]*(i+1)%mod;
}
ll C(ll a,ll b)
{
    if(b>a)
        return 0;
    if(b==0)
        return 1;
    return fac[a]*inv[b]%mod*inv[a-b]%mod;//计算组合数
}
ll dfs(int st,int en)
{
    ll cnt=1;
    for(int i=0; i<q[st].size(); i++)
    {
        if(q[st][i]==en) continue;
        ll t=dfs(q[st][i],st);//找左边有多少个结点
        cnt+=t;
        ans=(ans+ss-C(t,k)-C(n-t,k))%mod;
    }
    return cnt;
}
int main()
{
    getjni();
    while(scanf("%lld%lld",&n,&k)!=EOF)
    {
        ans=0;
        ss=C(n,k);
        for(int i=1; i<=n; i++)
            q[i].clear();
        for(int i=1; i<n; i++)
        {
            ll u,v;
            scanf("%lld%lld",&u,&v);
            q[u].push_back(v);
            q[v].push_back(u);
        }
        dfs(1,-1);
        printf("%lld\n",(ans+mod)%mod);
    }
}

51nod 1677——treecnt相关推荐

  1. 51Nod 1677 treecnt

    容斥 按照套路,按边考虑.一条边能贡献的答案是选的k个点分居两侧的方案数.发现这东西很难求.于是转成容斥求k个点归于一侧的方案数. #include<cstdio> #define N 1 ...

  2. 1677 treecnt(贡献)

    1677 treecnt 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 给定一棵n个节点的树,从1到n标号.选择k个点,你需要选择一些边使得这k个点通过选择的边联 ...

  3. treecnt 51Nod - 1677

    给定一棵n个节点的树,从1到n标号.选择k个点,你需要选择一些边使得这k个点通过选择的边联通,目标是使得选择的边数最少. 现需要计算对于所有选择k个点的情况最小选择边数的总和为多少. 样例解释: 一共 ...

  4. 51nod 1617 奇偶数组

    传送门 回来看一眼51nod,发现自己掉到rank4了,赶紧切道题回rank3. 一眼不会做,这种东西应该慢慢找规律吧--然后看到数据范围其实比较小,应该是单次log的,那是不是可以分治啊. #inc ...

  5. 1677: [Usaco2005 Jan]Sumsets 求和

    1677: [Usaco2005 Jan]Sumsets 求和 Time Limit: 5 Sec  Memory Limit: 64 MB Submit: 626  Solved: 348 [Sub ...

  6. 51NOD 1773:A国的贸易——题解

    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1773 参考1:FWT讲解 https://www.cnblogs.com ...

  7. 51nod 1040:最大公约数之和(数论)

    题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1040 给出一个n,求1-n这n个数,同n的最大公约数的和. ...

  8. (DP)51NOD 1183 编辑距离

    编辑距离,又称Levenshtein距离(也叫做Edit Distance),是指两个字串之间,由一个转成另一个所需的最少编辑操作次数.许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除 ...

  9. 斜率小于0的连线数量 51Nod - 1107 (树状数组+离散化)

    二维平面上N个点之间共有C(n,2)条连线.求这C(n,2)条线中斜率小于0的线的数量. 二维平面上的一个点,根据对应的X Y坐标可以表示为(X,Y).例如:(2,3) (3,4) (1,5) (4, ...

最新文章

  1. 利用硅光子学的移动心脏监护仪
  2. [置顶] ros的navigation之———gmapping应用详解(in ros)
  3. JSON转换和毫秒时间
  4. (转)Windows重启延迟删除,重命名技术原理
  5. 从Google Wave和XML看软件复杂性之争,互联网营销
  6. 手机号正则_这20个正则表达式,对你有大帮助,快来Make
  7. asp.net ajax1.0基础回顾(五):调用ASMX(WebService)
  8. 简单聊聊C#中lock关键字
  9. 学习C/C++:伴随我成长的编程书!
  10. Closure 代表匿名函数的类
  11. Linux分卷压缩zip文件命令,linux下的几种分卷压缩命令
  12. charles——教程——转载
  13. 后台获取用户登录信息
  14. 喝杯水都能泄露指纹?屏下指纹识别设备被攻破
  15. C#在一个form中改变另一个form中控件的内容、C#做登录界面并且密码显示为*
  16. oracle物理文件删除如何恢复,Oracle数据文件物理删除后的恢复
  17. 前端超出文字显示省略号
  18. 市面上的计算机培训机构 哪家实力最强
  19. 北京兄弟连web前端
  20. 解决Graphviz无法显示决策树中文问题

热门文章

  1. 京东月薪8万快递员:真正牛逼的人,都拥有这个特质
  2. 【JavaSE系列】基础经典编程题
  3. 如何给批量的图片命名(以序号递增的形式)?
  4. bootstrap4 input-spinner数字增减框的使用
  5. 支付宝-相互保,创新。
  6. 这世上,真有人会陪你手握屠龙刀,杀得生活措手不及!
  7. 苹果电脑python编程里面怎么切到中文_mac下的 idle为何不能输入中文?该如何解决?...
  8. 【航线运输驾驶员理论考试】气象学
  9. 《神经网络和深度学习 学习笔记》(二)人工神经网络简介
  10. 个人形象设计之色彩季型分析