【BZOJ 1005】无根树的Prufer数列

今天看了Prufer数列这个东西。

每一个Prufer数列和无根树是一一对应的。所以求出有多少符合要求的Prufer数列即可。

点i在Prufer数列中的出现次数为i的度数 - 1。

代码如下:【用分解质因数的方法,避免了高精除】

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <iostream>

using namespace std;

const int N = 10000 + 5, Prime_N = 1450 + 5;

int n, Prime[Prime_N], A[N], p[Prime_N], Ans[N], P = 0, Bg, l, K;

bool isPrime[N];

void Add(int num, int Flag)
{
    for (int i = 1; i <= P; i++)
    {
        if (Prime[i] > num) break;
        while (num % Prime[i] == 0)
        {
            p[i] += Flag;
            num /= Prime[i];
        }
    }
}

void Cheng(int num)
{
    for (int i = 1; i <= l; i++) Ans[i] *= num;
    for (int i = 1; i <= l; i++)
    {
        Ans[i + 1] += Ans[i] / 10;
        Ans[i] %= 10;
    }
    while (Ans[l + 1])
    {
        l++;
        Ans[l + 1] += Ans[l] / 10;
        Ans[l] %= 10;
    }
}

int main()
{
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) scanf("%d", A + i);
    for (int i = 1; i <= n; i++) isPrime[i] = true;
    isPrime[1] = false;
    for (int i = 2; i <= n; i++)
    {
        if (isPrime[i]) Prime[++P] = i;
        for (int j = 1; j <= P && i * Prime[j] <= n; j++)
            isPrime[i * Prime[j]] = false;
    }
    memset(p, 0, sizeof(p));
    Bg = n - 2;
    K = n;
    for (int i = 1; i <= n; i++)
    {
        if (A[i] != -1)
        {
            K--;
            for (int j = 1; j <= A[i] - 1; j++)
            {
                Add(Bg, 1);
                Bg--;
                Add(j, -1);
            }
        }
    }
    Ans[1] = 1;
    l = 1;
    for (int i = 1; i <= P; i++)
        for (int j = 1; j <= p[i]; j++)
            Cheng(Prime[i]);
    for (int i = 1; i <= Bg; i++) Cheng(K);
    for (int i = l; i >= 1; i--) printf("%d", Ans[i]);
    printf("\n");
    return 0;
}

【BZOJ 1005】无根树的Prufer数列

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

【BZOJ 1005】无根树的Prufer数列的相关文章

prufer数列

涨姿势---prufer数列 一. 简介 Prufer数列是无根树的一种数列.在组合数学中,Prufer数列由有一个对于顶点标过号的树转化来的数列,点数为n的树转化来的Prufer数列长度为n-2.它可以通过简单的迭代方法计算出来.它由Heinz Prufer于1918年在证明cayley定理时首次提出. 二. (1)将树转换为prufer数列的方法. 总体的思路是迭代删点,直到原图中只剩下两个点.对于一棵树T,我们已经将每次找到树中标号最小的叶子结点,将这个叶子结点以及与它相邻的边删去,将与叶

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

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

【组合数学】【高精度】【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 1005: [HNOI2008]明明的烦恼 prufer编号&amp;&amp;生成树计数

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

[BZOJ1005]Prufer数列+排列组合

一棵树的Prufer数列 每次在剩下的树中找到标号最小的叶子节点(对于无根树而言即是度数为1的节点),删去. 同时将其父节点(即与其相连的唯一点)加入Prufer数列当中. 一个Prufer数列所对应的树 G集合开始为空集 设当前处理到Prufer数列的第i项,找到G集合中未出现且在Prufer[i..n-2]未出现过的标号最小的节点,设其为u. 将u加入集合G中,并将u与Prufer[i]连一条边. 最后将在G集合中仍未出现的两个点之间连一条边(其中必定有一个是n). 来思考一下为何可以还原成

BZOJ 1005 明明的烦恼 (组合数学)

题解:n为树的节点数,d[ ]为各节点的度数,m为无限制度数的节点数. 则             所以要求在n-2大小的数组中插入tot各序号,共有种插法: 在tot各序号排列中,插第一个节点的方法有种插法: 插第二个节点的方法有种插法: ......... 另外还有m各节点无度数限制,所以它们可任意排列在剩余的n-2-tot的空间中,排列方法总数为 根据乘法原理: #include <cstdio> #include <cmath> int n,m,tot,i,j,d,down

【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: [HNOI2008]明明的烦恼 Purfer数列

Purfer数列: http://www.cnblogs.com/zhj5chengfeng/p/3278557.html 题目大意 自从明明学了树的结构,就对奇怪的树产生了兴趣...... 给出标号为 1 到 N 的点,以及某些点最终的度数,允许在任意两点间连线,可产生多少棵度数满足要求的树? Input 第一行为 N(0<N<=1000),接下来 N 行,第 i+1 行给出第 i 个节点的度数 Di,如果对度数不要求,则输入 -1 Output 一个整数,表示不同的满足要求的树的个数,无解

BZOJ 1005 明明的烦恼(prufer序列+高精度)

有一种东西叫树的prufer序列,一个树的与一个prufer序列是一一对应的关系. 设有m个度数确定的点,这些点的度为dee[i],那么每个点在prufer序列中出现了dee[i]-1次. 由排列组合可以推出公式.需要用高精度. #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define M 1100 using namespace std; typede