BZOJ 1211: [HNOI2004]树的计数

传送门:HTTP://www.lydsy.com/JudgeOnline/problem.php ID = 1211

题意:给你n个点和每个点的度求符合这些结构树的方案数

思路:参照http://blog.csdn.net/sinat_27410769/article/details/46596739

这里直接给出公式sum = sigma d [i] -1 ans = sum!/(d [1] -1)*(d [2] -1)* .... *(d [n] -1)

特别说明:n == 1 d [1] == 0需要特判

码:

 

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int mod = 1e9 + 7;
const int maxn = 160;
inline void read(int &x){x = 0;char p = getchar();while(!(p <= '9' && p >= '0'))p = getchar();while(p <= '9' && p >= '0')x *= 10, x += p - 48, p = getchar();}
LL prime[25100],is[25100],pricnt=0;
inline void init()
{
    is[1]=1;
    for(int i=2;i<=25000;i++)
    {
        if(is[i] == 0) prime[++pricnt]=i;
        for(int j=1;j<=pricnt;j++)
        {
            if(i*prime[j] > 25000ll) break;
            is[i*prime[j]]=1;
        }
    }
}
LL d[160];int n;
LL A[25010],B[25010];
LL mul(LL a,LL b)
{
    LL c=1ll;
    while(b > 0)
    {
        if(b&1) c*=a;
        b>>=1;
        a*=a;
    }
    return c;
}
void Fac(LL x,LL num[])
{
    if(x == 0 || x == 1) return;
    for(int i=1;i<=pricnt;i++)
    {
        while(x%prime[i] == 0) x/=prime[i],num[i]++;
        if(x == 1) return;
    }
}
int main()
{
    init();
    while(scanf("%d",&n)!=EOF)
    {
        int flag=0;LL sum=0;
        memset(A,0,sizeof A);
        memset(B,0,sizeof B);
        for(int i=1;i<=n;i++)
        {
            scanf("%lld",&d[i]);
            if(d[i] == 0) flag=1;
            sum+=d[i]-1;
        }
        if(sum +n !=(n-1)*2ll) flag=1;
        if(n == 1  && d[1] == 0) puts("1");
        else if(flag == 1) puts("0");
        else
        {
            LL ans=1ll;
            for(LL i=1;i<=sum;i++) Fac(i,A);
            for(int i=1;i<=n ;i++) Fac(d[i]-1ll,B);
            for(int i=1;i<=pricnt;i++)
            {
                A[i]-=B[i];
                ans*=mul(prime[i],A[i]);
            }
            printf("%lld\n",ans);
        }
    }
    return 0;
}

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值