【组合数学】【prufer数列】【HNOI 2004】【bzoj 1211】树的计数

1211: [HNOI2004]树的计数

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 1565  Solved: 512

Description

一个有n个结点的树,设它的结点分别为v1, v2, …, vn,已知第i个结点vi的度数为di,问满足这样的条件的不同的树有多少棵。给定n,d1, d2, …, dn,编程需要输出满足d(vi)=di的树的个数。

Input

第一行是一个正整数n,表示树有n个结点。第二行有n个数,第i个数表示di,即树的第i个结点的度数。其中1<=n<=150,输入数据保证满足条件的树不超过10^17个。

Output

输出满足条件的树有多少棵。

Sample Input

4
2 1 2 1

Sample Output

2

题解:

是明明的烦恼的弱化版。。做法大体相同,不用高精度真是开心。

Code:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 210
#define LL long long

int n,s,d[N],su[N],ys[N];
LL jc[30],ans;

int in(){
    int x=0; char ch=getchar();
    while (ch<‘0‘ || ch>‘9‘) ch=getchar();
    while (ch>=‘0‘ && ch<=‘9‘) x=x*10+ch-‘0‘,ch=getchar();
    return x;
}

void init(){
    jc[0]=jc[1]=1;
    for (int i=2; i<=25; i++) jc[i]=jc[i-1]*(LL)i;

    for (int i=2; i<=N; i++){
        bool f=true;
        for (int j=2; j<=sqrt(i); j++)
            if (!(i%j)){
                f=false; break;
            }
        if (f) su[++su[0]]=i;
    }
}

void fenjie(int x,int y){
    for (int i=1; i<=su[0]; i++){
        if (x<=1) return;
        while (!(x%su[i]))
            ys[i]+=y,x/=su[i];
    }
}

int main(){
    scanf("%d",&n);
    if (n==1){
        int x=in();
        if (!x) ans=1;
        else ans=0;
        printf("%d\n",ans);
        return 0;
    }
    for (int i=1; i<=n; i++){
        d[i]=in();
        if (!d[i]){
            printf("0\n");
            return 0;
        }
        d[i]--,s+=d[i];
    }
    if (s!=n-2){
        printf("0\n");
        return 0;
    }

    init(); ans=1;
    if (n-2<=25) fenjie(jc[n-2],1);
    for (int i=1; i<=n; i++)
        fenjie(jc[d[i]],-1);
    for (int i=1; i<=su[0]; i++)
        while (ys[i]--) ans*=su[i];

    printf("%d\n",ans);
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-11 14:59:15

【组合数学】【prufer数列】【HNOI 2004】【bzoj 1211】树的计数的相关文章

【bzoj1284】【HNOI2004】【树的计数】【组合数学+prufer数列】

Description 一个有n个结点的树,设它的结点分别为v1, v2, -, vn,已知第i个结点vi的度数为di,问满足这样的条件的不同的树有多少棵.给定n,d1, d2, -, dn,编程需要输出满足d(vi)=di的树的个数. Input 第一行是一个正整数n,表示树有n个结点.第二行有n个数,第i个数表示di,即树的第i个结点的度数.其中1<=n<=150,输入数据保证满足条件的树不超过10^17个. Output 输出满足条件的树有多少棵. Sample Input 4 2 1

BZOJ 1005 明明的烦恼(Prufer数列)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1005 题意:给出一棵树的某些节点的度数d,有些未给.问满足这个条件的树有多少种? 思路:(1)Prufer 数列是无根树的一种数列.由一棵树可以构造出一个Prufer数列,Prufer数列可转化为原来的树.由树生成Prufer的一种简单方法是每次找出标 号最小的叶子节点将其父节点添加到Prufer数列并将该叶子节点删除.直到最后只剩下两个节点时结束.比如下面的这个树按照我们刚才的方法生

BZOJ 1211: [HNOI2004]树的计数 purfer序列

1211: [HNOI2004]树的计数 Description 一个有n个结点的树,设它的结点分别为v1, v2, …, vn,已知第i个结点vi的度数为di,问满足这样的条件的不同的树有多少棵.给定n,d1, d2, …, dn,编程需要输出满足d(vi)=di的树的个数. Input 第一行是一个正整数n,表示树有n个结点.第二行有n个数,第i个数表示di,即树的第i个结点的度数.其中1<=n<=150,输入数据保证满足条件的树不超过10^17个. Output 输出满足条件的树有多少棵

【组合数学】【高精度】【prufer数列】【HNOI 2008】【bzoj 1005】明明的烦恼

1005: [HNOI2008]明明的烦恼 Time Limit: 1 Sec Memory Limit: 162 MB Submit: 3217 Solved: 1290 Description 自从明明学了树的结构,就对奇怪的树产生了兴趣-- 给出标号为1到N的点,以及某些点最终的度数,允许在任意两点间连线,可产生多少棵度数满足要求的树? Input 第一行为N(0 < N < = 1000),接下来N行,第i+1行给出第i个节点的度数Di,如果对度数不要求,则输入-1 Output 一个

BZOJ 1211: [HNOI2004]树的计数( 组合数学 )

知道prufer序列就能写...就是求个可重集的排列...先判掉奇怪的情况, 然后答案是(N-2)!/π(d[i]-1)! --------------------------------------------------------------------------- #include<cstdio> #include<algorithm> #include<cstring> using namespace std; typedef long long ll; c

【BZOJ 1211】 1211: [HNOI2004]树的计数 (prufer序列、计数)

1211: [HNOI2004]树的计数 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2468  Solved: 868 Description 一个有n个结点的树,设它的结点分别为v1, v2, -, vn,已知第i个结点vi的度数为di,问满足这样的条件的不同的树有多少棵.给定n,d1, d2, -, dn,编程需要输出满足d(vi)=di的树的个数. Input 第一行是一个正整数n,表示树有n个结点.第二行有n个数,第i个数表示di,即

【BZOJ】【1211】【HNOI2004】树的计数

Prufer序列+组合数学 嗯哼~给定每个点的度数!求树的种数!那么很自然的就想到是用prufer序列啦~(不知道prufer序列的……自己再找找资料吧,这里就不放了,可以去做一下BZOJ1005明明的烦恼) 那么我们令每个点的度数v[i]-1,得到每个节点在prufer序中的出现次数! 现在就是求这个prufer序有多少种了……有两种做法: 1.多重集排列数:n个元素,每种元素有a[i]个,求全排列的方案数,自己随便yy一下就可以得到$$ans=\frac{n!}{\prod (a[i]!)}

【BZOJ 1005】无根树的Prufer数列

今天看了Prufer数列这个东西. 每一个Prufer数列和无根树是一一对应的.所以求出有多少符合要求的Prufer数列即可. 点i在Prufer数列中的出现次数为i的度数 - 1. 代码如下:[用分解质因数的方法,避免了高精除] #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <iostream> using namesp

bzoj 1211 [HNOI2004]树的计数

[HNOI2004]树的计数 Description 一个有n个结点的树,设它的结点分别为v1, v2, …, vn,已知第i个结点vi的度数为di,问满足这样的条件的不同的树有多少棵.给定n,d1, d2, …, dn,编程需要输出满足d(vi)=di的树的个数. Input 第一行是一个正整数n,表示树有n个结点.第二行有n个数,第i个数表示di,即树的第i个结点的度数.其中1<=n<=150,输入数据保证满足条件的树不超过10^17个. Output 输出满足条件的树有多少棵. Samp