• [HNOI2004]树的计数


    [HNOI2004]树的计数

    一棵有n个有标号节点的树,设它第i个节点的度数为(v_i),询问这样的树的个数,1<=n<=150。

    显然为树的组合计数问题,与度数有关,考虑prefur序列,不难得知在prefur序列中,如果第i个节点的度数为(v_i),那么i将在序列中出现(v_i-1)次,所以答案就是

    [ans=frac{(n-2)!}{(v_1-1)!(v_2-1)!...(v_n-1)!} ]

    按照质因数分解的方式处理阶乘即可,注意判树是否成立。

    参考代码:

    #include <iostream>
    #include <cstdio>
    #define il inline
    #define ri register
    #define ll long long
    using namespace std;
    bool check[251];
    int d[151],prime[101],pt,tr[101];
    il ll pow(ll,ll);
    il void sieve(int);
    int main(){
        int n,i,j,k,tt(0);
        scanf("%d",&n);ll ans(1);
        if(n==1)return scanf("%d",&n),n?puts("0"):puts("1"),0;
        for(i=1;i<=n;++i){
            scanf("%d",&d[i]),tt+=d[i]-1;
            if(!d[i])return puts("0"),0;
        }if(tt!=n-2)return puts("0"),0;
        sieve(n);
        for(i=1;i<=pt;++i)for(j=n-2;j;j/=prime[i])tr[i]+=j/prime[i];
        for(i=1;i<=n;++i)
            for(j=1;j<=pt;++j)
                for(k=d[i]-1;k;k/=prime[j])
                    tr[j]-=k/prime[j];
        for(i=1;i<=n;++i)ans*=pow(prime[i],tr[i]);
        printf("%lld",ans);
        return 0;
    }
    il ll pow(ll x,ll y){
        ll ans(1);
        while(y){
            if(y&1)ans*=x;
            x*=x,y>>=1;
        }return ans;
    }
    il void sieve(int n){
        int i,j;check[1]|=true;
        for(i=2;i<=n;++i){
            if(!check[i])prime[++pt]=i;
            for(j=1;j<=pt&&i*prime[j]<=n;++j){
                check[prime[j]*i]|=true;
                if(!(i%prime[j]))break;
            }
        }
    }
    
  • 相关阅读:
    《深入浅出WPF》4.0x名称空间
    《深入浅出WPF》3.0 XAML语法
    DataGridview 自动切换到 下一行
    C# 生成条形码图片,效果不错
    将DataTable 导出为csv
    DataTable,DataGridVIew转换到xls 方法 (转)
    NPOI读取Excel 数据 转。。。
    修改 字段大小
    VC
    统计每天 指定 时间段内 的数据
  • 原文地址:https://www.cnblogs.com/a1b3c7d9/p/10853057.html
Copyright © 2020-2023  润新知