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; }
posted on 2018-02-02 14:43 2855669158 阅读(128) 评论(0) 编辑 收藏 举报