51nod1805 小树

题意:输入N,M,(2<=n, m<=1000000)一颗有标号无根树n个节点,有m个叶子节点,问有多少颗满足条件的树

题解:一颗有标号的无根树可以一一对应一个prufer序列,有一个定理:prufer序列中出现数字的次数+1是这个数字标号的度数,那么这里可以知道度数为1的有m个,也就是问恰好有1-n中的n-m种数且长度为n-2的序列有多少个,容斥+组合数

 

#include <bits/stdc++.h>
#define ll long long
#define maxn 1000100
using namespace std;
const ll mod = 1e9+7;
ll fc[maxn], fi[maxn];
ll f(ll a,ll b){
    ll ans = 1;
    while(b){
        if(b&1) ans = ans*a%mod;
        a = a*a%mod;
        b >>= 1;
    }
    return ans;
}
void init(){
    fc[0] = 1;
    for(ll i=1;i<maxn;i++) fc[i] = fc[i-1]*i%mod;
    fi[maxn-1] = f(fc[maxn-1], mod-2);
    for(ll i=maxn-1;i>=1;i--) fi[i-1] = fi[i]*i%mod;
}
ll c(ll n,ll m){
    return fc[n]*fi[m]%mod*fi[n-m]%mod;
}
int main(){
    init();
    ll n, m, ans = 0;
    scanf("%lld%lld", &n, &m);
    if(n == 2) return 0*printf("1\n");
    for(ll i=n-m;i>=1;i--){
        if((n-m-i)&1) ans -= c(n-m, i)*f(i, n-2)%mod;
        else ans += c(n-m, i)*f(i, n-2)%mod;
        ans = (ans+mod)%mod;
    }
    printf("%lld\n", ans*c(n, n-m)%mod);
    return 0;
}

 

转载于:https://www.cnblogs.com/Noevon/p/8405100.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值