1211: [HNOI2004]树的计数

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 3432  Solved: 1295
[Submit][Status][Discuss]

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
 
 
 

先丟几个Prufer序列的性质:

1.与无根树一一对应。

2.度数为$d_i$的点会在Prufer序列中出现$d_i-1$次。

3.一个$n$个节点的完全图的生成树个数为$n^{n-2}$

  解释一下:prufer序列长为$n-2$,每个位置有$n$种可能性。

4.对于给定每个点度数的无根树,共有$\frac{(n-2)!}{\prod \limits _{i=1}^n {(d_i-1)!}}$种情况。

  其实就是$d_i-1$个$i$的可重全排列。

那么这道题就用上面这个结论切掉就好了。求组合数直接分解质因数,记得要特判$n==1$及不联通的情况。

  1. #include<cstdio>
  2. #include<iostream>
  3. #include<cstring>
  4. const int N=;
  5. int d[N],n;
  6. int vis[N],pri[N],res[N],tot,sum,ans[N*],bu[N];
  7. void getprime()
  8. {
  9. for(int i=;i<=n;i++)
  10. {
  11. if(!vis[i])pri[++tot]=i,res[i]=tot;
  12. for(int j=;j<=tot;j++)
  13. {
  14. if(pri[j]*i>n)break;
  15. vis[i*pri[j]]=;res[i*pri[j]]=j;
  16. if(i%pri[j]==)break;
  17. }
  18. }
  19. }
  20. void divi(int x,int val)
  21. {
  22. while(x!=)bu[res[x]]+=val,x/=pri[res[x]];
  23. }
  24. void mult(int a[],int x)
  25. {
  26. int k=;
  27. for(int i=;i<=a[];i++)
  28. {
  29. int tmp=a[i]*x+k;
  30. a[i]=tmp%;
  31. k=tmp/;
  32. }
  33. while(k)a[++a[]]=k%,k/=;
  34. }
  35. int main()
  36. {
  37. scanf("%d",&n);
  38. if(n==)
  39. {
  40. int deg;
  41. scanf("%d",&deg);
  42. if(!deg)puts("");
  43. else puts("");
  44. return ;
  45. }
  46. getprime();
  47. for(int i=;i<=n;i++)
  48. {
  49. scanf("%d",&d[i]);
  50. if(!d[i])
  51. {
  52. puts("");
  53. return ;
  54. }
  55. sum+=d[i]-;
  56. }
  57. if(sum!=n-)
  58. {
  59. puts("");
  60. return ;
  61. }
  62. for(int i=n-;i>=;i--)
  63. divi(i,);
  64. for(int i=;i<=n;i++)
  65. {
  66. for(int j=d[i]-;j>=;j--)
  67. divi(j,-);
  68. }
  69. ans[]=ans[]=;
  70. for(int i=;i<=tot;i++)
  71. while(bu[i]--)mult(ans,pri[i]);
  72. for(int i=ans[];i;i--)
  73. printf("%d",ans[i]);
  74. return ;
  75. }

1005: [HNOI2008]明明的烦恼

Time Limit: 1 Sec  Memory Limit: 162 MB
Submit: 7125  Solved: 2818
[Submit][Status][Discuss]

Description

  自从明明学了树的结构,就对奇怪的树产生了兴趣......给出标号为1到N的点,以及某些点最终的度数,允许在
任意两点间连线,可产生多少棵度数满足要求的树?

Input

  第一行为N(0 < N < = 1000),
接下来N行,第i+1行给出第i个节点的度数Di,如果对度数不要求,则输入-1

Output

  一个整数,表示不同的满足要求的树的个数,无解输出0

Sample Input

3
1
-1
-1

Sample Output

2

HINT

  两棵树分别为1-2-3;1-3-2

本题的问题在于有的点度数是不确定的。

所以我们先求出$sum=\sum d_i-1$,之后从总长度$n-2$中选出这些

对于剩下的不确定度数的部分,我们设已知度数点的个数为$cnt$

那么现在有$n-2-sum$个位置可以任意排列$n-cnt$个点

易得最终答案为

$C_{n-2}^{sum}*\frac{(n-2)!}{\prod \limits _{i=1}^{cnt} {(d_i-1)!}}*(n-cnt)^{n-2-sum}$

  1. #include<cstdio>
  2. #include<iostream>
  3. #include<cstring>
  4. using namespace std;
  5. typedef long long ll;
  6. const int N=;
  7. int d[N],n;
  8. int vis[N],pri[N],res[N],tot,sum,cnt,ans[N*],bu[N];
  9. void getprime()
  10. {
  11. for(int i=;i<=n;i++)
  12. {
  13. if(!vis[i])pri[++tot]=i,res[i]=tot;
  14. for(int j=;j<=tot;j++)
  15. {
  16. if(pri[j]*i>n)break;
  17. vis[i*pri[j]]=;res[i*pri[j]]=j;
  18. if(i%pri[j]==)break;
  19. }
  20. }
  21. }
  22. void divi(int x,int val)
  23. {
  24. while(x!=)bu[res[x]]+=val,x/=pri[res[x]];
  25. }
  26. void mult(int a[],int x)
  27. {
  28. int k=;
  29. for(int i=;i<=a[];i++)
  30. {
  31. int tmp=a[i]*x+k;
  32. a[i]=tmp%;
  33. k=tmp/;
  34. }
  35. while(k)a[++a[]]=k%,k/=;
  36. }
  37.  
  38. int main()
  39. {
  40. scanf("%d",&n);
  41. getprime();
  42. for(int i=;i<=n;i++)
  43. {
  44. scanf("%d",&d[i]);
  45. if(d[i]!=-)sum+=d[i]-,cnt++;
  46. }
  47. for(int i=n-;i>=;i--)
  48. divi(i,);
  49. for(int i=n--sum;i>=;i--)
  50. divi(i,-);
  51. for(int i=;i<=n;i++)
  52. {
  53. if(d[i]!=-)
  54. {
  55. for(int j=d[i]-;j>=;j--)
  56. divi(j,-);
  57. }
  58. }
  59. ans[]=ans[]=;
  60. for(int i=;i<=n--sum;i++)
  61. mult(ans,n-cnt);
  62. for(int i=;i<=tot;i++)
  63. while(bu[i])mult(ans,pri[i]),bu[i]--;
  64. for(int i=ans[];i>=;i--)
  65. printf("%d",ans[i]);
  66. return ;
  67. }

bzoj1211树的计数 x bzoj1005明明的烦恼 题解(Prufer序列)的更多相关文章

  1. 【BZOJ1005】[HNOI2008]明明的烦恼(prufer序列)

    [BZOJ1005][HNOI2008]明明的烦恼(prufer序列) 题面 BZOJ 洛谷 题解 戳这里 #include<iostream> #include<cstdio> ...

  2. [HNOI2008][bzoj 1005]明明的烦恼(prufer序列)

    1005: [HNOI2008]明明的烦恼 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 7121  Solved: 2816[Submit][Stat ...

  3. 2021.07.19 P2624 明明的烦恼(prufer序列,为什么杨辉三角我没搞出来?)

    2021.07.19 P2624 明明的烦恼(prufer序列,为什么杨辉三角我没搞出来?) [P2624 HNOI2008]明明的烦恼 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn ...

  4. HNOI2004 树的计数 和 HNOI2008 明明的烦恼

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

  5. [HNOI2008]明明的烦恼(prufer序列,高精度,质因数分解)

      prufer序列 定义 Prufer数列是无根树的一种数列.在组合数学中,Prufer数列由有一个对于顶点标过号的树转化来的数列,点数为n的树转化来的Prufer数列长度为n-2. 描述 eg 将 ...

  6. 【洛谷2624_BZOJ1005】[HNOI2008] 明明的烦恼(Prufer序列_高精度_组合数学)

    题目: 洛谷2624 分析: 本文中所有的 "树" 都是带标号的. 介绍一种把树变成一个序列的工具:Prufer 序列. 对于一棵 \(n\) 个结点的树,每次选出一个叶子(度数为 ...

  7. [BZOJ1005][HNOI2008]明明的烦恼 数学+prufer序列+高精度

    #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int N; ...

  8. [HNOI2004][bzoj1211] 树的计数(prufer序列)

    1211: [HNOI2004]树的计数 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3432  Solved: 1295[Submit][Stat ...

  9. BZOJ1005明明的烦恼 Prufer + 分解質因數 + 高精度

    @[高精度, Prufer, 質因數分解] Description 自从明明学了树的结构,就对奇怪的树产生了兴趣......给出标号为1到N的点,以及某些点最终的度数,允许在 任意两点间连线,可产生多 ...

随机推荐

  1. Postgresql临时表

    PostgreSQL支持两类临时表,会话级和事务级临时表.在会话级别的临时表中,在整个会话的生命周期中,数据一直保存.事务级临时表,数据只存在于这个事务的生命周期中.不指定临时表的属性, Postgr ...

  2. 仅当使用了列列表并且 IDENTITY_INSERT 为 ON 时,才能为表'XXX'中的标识列指定显式值。

    (来自:https://zhidao.baidu.com/question/494717175.html)第一条回复,原因和例子都有了,解释的很好. 插入数据时,自增长列是系统自动处理,不需要你来指定 ...

  3. Java学习之面向对象---继承

    继承:子继承父,子可以拥有父的所有. 继承的好处: 1.提高了代码的复用性 2.让类与类之间产生了关系.有了这个关系,才有了多态的特性 Java 只支持单继承,不支持多继承 class A { voi ...

  4. 数据分析系列篇:玩转excel

    数据分析系列篇:玩转excel 不知道现在怎么也变得这么鸡婆,连excel都要准备写一篇.没办法,还有很多不是做数据的小伙伴们不会excel啊,抱着不抛弃.不放弃的态度,就讲下excel如何玩转.其实 ...

  5. Python编写购物小程序

    购物车要求: 用户名和密码存放于文件中 启动程序后,先登录,登录成功则让用户输入工资,然后打印商品列表,失败则重新登录,超过三次则退出程序 允许用户根据商品编号购买商品 用户选择商品后,检测余额是否够 ...

  6. activiti7查询流程定义的相关信息

    package com.zcc.activiti02; import org.activiti.engine.ProcessEngine;import org.activiti.engine.Proc ...

  7. Cocos2d-x 发布 Android

    Cocos2d-x 发布 Android 前置需求: Android NDK Android SDK OR Eclipse ADT Bundle Android AVD target installe ...

  8. docker内的服务无法获取用户真实IP

    原文:blog.baohaipeng.top 背景:MySQL数据库和Redis运行在宿主机上(Linux),server运行在docker内,web运行在Nginx内(Nginx运行在docker内 ...

  9. Spring JAR下载地址

    包含3.2版本及以上 http://repo.spring.io/libs-release-local/org/springframework/spring/ 包含从2.0开始的所有版本 http:/ ...

  10. 深入JAVA虚拟机笔记-垃圾收集器与内存分配策略

    第三章:垃圾收集器与内存分配 问题:1.哪些内存需要回收 2.什么时候回收 3.怎么回收 回收方法区: