zoukankan      html  css  js  c++  java
  • HNOI2004 树的计数 | HNOI2008 明明的烦恼

    题目链接:戳我

    prufer序列的问题。

    prufer序列和无根树是一一对应的。而且在树中度数为k的点,在prufer序列中的出现次数为(k-1)次。

    根据有限制次数的可重复元素的排列计数公式,我们可以知道答案是(frac{(n-2)!}{(du[1]-1) imes (du[2]-1) imes ... imes (du[n]-1)})

    因为乘法中间可能会爆long long,所以采用分解质因数的方式。

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<cstdio>
    #define MAXN 100010
    using namespace std;
    int n,m,tot,cnt;
    int d[MAXN],num[MAXN],prime[MAXN];
    long long ans=1;
    long long s[MAXN];
    inline bool check(int x)
    {
        for(int i=2;i<=sqrt(x);i++)
            if(x%i==0) return false;
        return true;
    }
    inline void get_prime()
    {
        for(int i=2;i<=150;i++)
            if(check(i))
                prime[++cnt]=i;
    }
    inline void solve(long long x,int f)
    {
        for(int i=1;i<=cnt;i++)
        {
            if(x<=1) return;
            while(x%prime[i]==0)
                num[i]+=f,x/=prime[i];
        }
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        #endif
        s[1]=1;
        for(int i=2;i<=22;i++) s[i]=s[i-1]*i;
        get_prime();
        scanf("%d",&n);
        if(n==1)
        {
            int x;
            scanf("%d",&x);
            if(!x) printf("1
    ");
            else printf("0
    ");
            return 0;
        }
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&d[i]);
            if(!d[i]){printf("0
    ");return 0;}
            d[i]--;
            tot+=d[i];
        }
        if(tot!=n-2){printf("0
    ");return 0;}
        solve(s[n-2],1);
        for(int i=1;i<=n;i++) solve(s[d[i]],-1);
        for(int i=1;i<=cnt;i++)
            while(num[i]--)
                ans*=prime[i];
        printf("%lld
    ",ans);
        return 0;
    }
    

    这个题是明明的烦恼的弱化版。
    不过如果会做这个题,应该也会做那个题了。

    现在我们只知道cnt个点的最终度数,我们假设(sum=sum_{i=1}^n (du[i]-1))那么现在的prufer序列的种类数应该是(C_{n-2}^{sum} imes frac{sum!}{prod_{i=1}^{cnt} (du[i]-1)!})

    而剩下来还有(n-2-sum)个位置,每个位置都可以填入除了cnt这些点的其他所有点,所以刚才的式子乘上一个((n-cnt)^{n-2-sum})就行了。

  • 相关阅读:
    js点击弹出div层
    图片按比例缩小
    js标题文字向上滚动
    JS刷新当前页面
    图片缩放显示,不变形
    产品叠加搜索
    Oracle中DML基础知识
    Oracle中DDL的基础知识
    Sql多对多关系中外键的应用
    oracle 中sql语句的几个基本函数..
  • 原文地址:https://www.cnblogs.com/fengxunling/p/11163974.html
Copyright © 2011-2022 走看看