51nodwangyurzee的树

来源:互联网 发布:无线网访客网络 编辑:程序博客网 时间:2024/06/02 05:48

链接:http://www.51nod.com/contest/problem.html#!problemId=1806

题意:中文题。

分析:一个度数为d的点会在prufer序列中出现d-1次,而每一个prufer序列都对应一棵树,那么我们就可以直接用容斥原理+组合数学+prufer序列解决掉这题了。注意prufer序列长度为n-2,注意n=1的情况。

代码:

#include<map>#include<set>#include<cmath>#include<queue>#include<bitset>#include<math.h>#include<vector>#include<string>#include<stdio.h>#include<cstring>#include<iostream>#include<algorithm>#pragma comment(linker, "/STACK:102400000,102400000")using namespace std;const int N=2000010;const int mod=100000000;const int MOD1=1000000007;const int MOD2=1000000009;const double EPS=0.00000001;typedef long long ll;const ll MOD=1000000007;const int INF=1000000010;const ll MAX=1ll<<55;const double pi=acos(-1.0);typedef double db;typedef unsigned long long ull;int n,q[20],u[20],d[20];ll mul[N],inv[N],now[N];void deal(int n) {    mul[0]=now[0]=1;    mul[1]=inv[1]=now[1]=1;    for (int i=2;i<=n;i++) {        mul[i]=mul[i-1]*i%MOD;        inv[i]=(MOD-MOD/i)*inv[MOD%i]%MOD;        now[i]=now[i-1]*inv[i]%MOD;    }}ll C(ll n,ll m) {    if (n<m) return 0;    return mul[n]*now[m]%MOD*now[n-m]%MOD;}ll qpow(ll a,ll b) {    ll ret=1;    while (b) {        if (b&1) ret=ret*a%MOD;        a=a*a%MOD;b>>=1;    }    return ret;}int main(){    int i,j,g,m,bo,sum;    ll ans=0,tot;    scanf("%d%d", &n, &m);    for (i=0;i<m;i++) scanf("%d%d", &u[i], &d[i]);    deal(n);    for (i=0;i<(1<<m);i++) {        g=0;sum=0;bo=1;tot=1;        memset(q,0,sizeof(q));        for (j=0;j<m;j++)        if (i&(1<<j)) {            if (q[u[j]]) { bo=0;break ; }            tot=tot*C(n-2-sum,d[j]-1)%MOD;            g++;q[u[j]]=1;sum+=d[j]-1;        }        if (!bo||sum>n-2) continue ;        tot=tot*qpow(n-g,n-2-sum)%MOD;        if (g&1) ans=(ans-tot)%MOD;        else ans=(ans+tot)%MOD;    }    if (n==1&&m==0) printf("1\n");    else printf("%I64d\n", (ans+MOD)%MOD);    return 0;}


0 0
原创粉丝点击