zoukankan      html  css  js  c++  java
  • P2290 [HNOI2004]树的计数【prufer序列】

    题意

    一个有 (n) 个节点的树,设它的节点分别为 (v_1,v_2,dots,v_n),已知第 (i) 个节点 (v_i) 的度数为 (d_i),问满足这样的条件的不同的树有多少棵。

    (1leq n leq 150)

    分析

    根据 ( ext{prufer}) 序列的性质,每棵树对应序列的长度均为 (n-2),每个编号 (i) 会在序列中出现 (d_i-1) 次。结合可重集合的排列公式,可得最终结果为:

    [ans=frac{(n-2)!}{prod_{i=1}^{n}(d_i-1)!} ]

    同时,考虑到无解的情况:

    • 出现点的度大于 (n-1) 的情况
    • (n>1) 时,出现点的度为 (0)
    • 各点的度数之和不等于 (2(n-1)) ,即 (sum{(d_i-1)} eq n-2)

    使用高精度或者 ( ext{python}),即可算出。

    代码

    #include <bits/stdc++.h>
    
    using namespace std;
    typedef long long ll;
    
    const ll scale=100000;
    struct number
    {
        int maxn=1010;
        ll di[1010];
        void clc()
        {
            for(int i=0;i<maxn;i++) di[i]=0;
        }
        int comp(const number &b)const//比较大小
        {
            if(di[0]>b.di[0]) return 1;
            if(di[0]<b.di[0]) return -1;
            for(int i=di[0];i>=1;i--)
            {
                if(di[i]>b.di[i]) return 1;
                if(di[i]<b.di[i]) return -1;
            }
            return 0;
        }
        number operator - (const number &b)const
        {
            number res,a;
            for(int i=0;i<=di[0];i++) a.di[i]=di[i];
            for(int i=1;i<=a.di[0];i++)
            {
                if(a.di[i]<b.di[i])
                {
                    a.di[i]+=scale;
                    a.di[i+1]--;
                }
                res.di[i]=a.di[i]-b.di[i];
            }
            res.di[0]=a.di[0];
            ll &p=res.di[0];
            while(res.di[p]==0&&p>=0) p--;
            return res;
        }
        number operator *(const number &b)const//高精度乘高精度
        {
            number res;
            for(int i=1;i<=di[0];i++)
            {
                for(int j=1;j<=b.di[0];j++)
                    res.di[i+j-1]=di[i]*b.di[j];
            }
            res.di[0]=di[0]+b.di[0];
            for(int i=1;i<=res.di[0];i++)
            {
                res.di[i+1]+=res.di[i]/scale;
                res.di[i]=res.di[i]%scale;
            }
            ll &p=res.di[0];
            while(res.di[p]==0&&p>=0) p--;
            return res;
        }
        number operator / (const number &b)const //高精度除高精度,默认大于
        {
            number res,a;
            res.clc();
            a.clc();
            for(int i=0;i<=di[0];i++) a.di[i]=di[i];
            int f=comp(b);
            while(f>=0)
            {
                a=a-b;
                res.di[1]++;
                int p=1;
                while(res.di[p]>0)
                {
                    res.di[p+1]+=res.di[p]/scale;
                    res.di[p]=res.di[p]%scale;
                    p++;
                }
                res.di[0]=p;
                f=a.comp(b);
            }
            //最终a中存余数
            ll &p=res.di[0];
            while(res.di[p]==0&&p>=0) p--;
            return res;
        }
        void print()
        {
            printf("%lld",di[di[0]]);
            int d=5;//根据具体的进制确定
            for(int i=di[0]-1;i>=1;i--)
                printf("%.5lld",di[i]);
            printf("
    ");
        }
    };
    void mul(number &a,int b)
    {
        for(int i=1;i<=a.di[0];i++)
            a.di[i]*=b;
        for(int i=1;i<=a.di[0]+10;i++)
        {
            a.di[i+1]+=a.di[i]/scale;
            a.di[i]=a.di[i]%scale;
        }
        a.di[0]+=10;
        ll &p=a.di[0];
        while(a.di[p]==0&&p>=0) p--;
    }
    int main()
    {
        int n,d,flag=1,tol=0;
        scanf("%d",&n);
        number x,y;
        x.clc();
        y.clc();
        x.di[0]=y.di[0]=1;
        x.di[1]=y.di[1]=1;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&d);
            tol+=d;
            if(d>n-1||(n>1&&d==0)) flag=0;
            for(int j=1;j<d;j++)
                mul(y,j);
        }
        if(tol!=2*(n-1)) flag=0;
        if(flag==0)
        {
            printf("0
    ");
            return 0;
        }
        //y.print();
        for(int i=1;i<n-1;i++)
            mul(x,i);
        //x.print();
        number ans=x/y;
        ans.print();
        return 0;
    }
    
    
  • 相关阅读:
    CF1375E Solution
    牛客暑期营2K Solution
    牛客暑期营1F Solution
    redux的使用
    react-routerV6.0的使用
    react配置emotion
    react项目中配置antd
    使用npx创建react+typescript项目
    【5】Redis从入门到放弃---秒杀案例(Redis的事务+锁机制+lua脚本)
    【四】Redis从入门到放弃---RedisTemplate操作Redis
  • 原文地址:https://www.cnblogs.com/1024-xzx/p/13626650.html
Copyright © 2011-2022 走看看