1005: [HNOI2008]明明的烦恼
Time Limit: 1 Sec Memory Limit: 162 MB
Submit: 6539 Solved: 2558
[Submit][Status][Discuss]
Description
自从明明学了树的结构,就对奇怪的树产生了兴趣......给出标号为1到N的点,以及某些点最终的度数,允许在
任意两点间连线,可产生多少棵度数满足要求的树?
Input
第一行为N(0 < N < = 1000),
接下来N行,第i+1行给出第i个节点的度数Di,如果对度数不要求,则输入-1
Output
一个整数,表示不同的满足要求的树的个数,无解输出0
Sample Input
1
-1
-1
Sample Output
HINT
两棵树分别为1-2-3;1-3-2
首先要知道 Prufer数列 和 节点度数 这种东西,自行Google。
Plufer数列有一下性质:
1、可以表示为任意一个长度为n-2的数列
2、任意一点的度数为d[i],则该节点在数列中出现d[i]-1次
3、因此数列的总长度为:
\[sum=\sum _{i=1}^{n} (d[i]-1)\]
得出这个总长度的前提是,所有度数已知,但题目并没有给出所有的度数。但是我们可以计算出已知n个点的度数,可以构造出多少种Prufer数列:
\[\frac{(n-2)!}{\prod _{i-1}^{n}(d[i]-1)!}\]
那么已知cnt个点的度数,可以构造出多少种Prufer数列呢?
\[C_{n-2}^{sum}\times \frac{sum!}{\prod _{i-1}^{n}(d[i]-1)!}\]
那么已知cnt个点的度数,n-cnt个点的度数未知,可以构造出多少种Prufer数列呢?
\[ans=C_{n-2}^{sum}\times\frac{sum!}{\prod _{i-1}^{n}(d[i]-1)!}\times(n-cnt)^{n-2-sum}\]
最终可以化简得:
\[ans=\frac{(n-2)!}{(n-2-sum)!\prod _{i-1}^{n}(d[i]-1)!}\times(n-cnt)^{n-2-sum}\]
沿用了之前高精度乘除单精度的模板,减少代码量(明明是增加了)
虽说质因数分解更能显示bigger。。。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iomanip>
using namespace std; const int MAXN=;
const int DLEN=;
const int WIDE=;
class BigNum
{
public:
int NUM[MAXN];
int L;
bool flag;
BigNum(){memset(NUM,,sizeof(NUM));L=;flag=;}
BigNum(const BigNum &T){memcpy(NUM,T.NUM,sizeof(NUM));L=T.L;flag=T.flag;}
BigNum(int n){memset(NUM,,sizeof(NUM));NUM[]=n;L=;while(NUM[L-]>=WIDE){NUM[L]+=NUM[L-]/WIDE;NUM[L-]%=WIDE;L++;}flag=;}
}; void Output(const BigNum T)
{
if(T.flag==) cout<<'-';
cout<<T.NUM[T.L-];
for(int i=T.L-;i>=;i--)
{
cout.width(DLEN);
cout.fill('');
cout<<T.NUM[i];
}
} BigNum Mult(const BigNum A,int B)
{
BigNum C(A);
int i,tmp,k=;
for(i=;i<C.L||k;i++)
{
tmp=C.NUM[i]*B+k;
k=tmp/WIDE;
C.NUM[i]=tmp%WIDE;
}
C.L=i;
return C;
} BigNum Div(const BigNum A,int B)
{
BigNum C(A);
int k=;
for(int i=C.L-;i>=;i--)
{
k=k*WIDE+C.NUM[i];
C.NUM[i]=k/B;
k%=B;
}
while(C.NUM[C.L-]==) C.L--;
return C;
} int n,sum,cnt;
int d[];
bool flag;
BigNum ans(); int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++)
{
scanf("%d",&d[i]);
if(d[i]==||d[i]>n-) flag=;
if(d[i]==-) continue;
sum+=d[i]-;
cnt++;
}
if(n==)
{
if(d[]==||d[]==-) printf("1\n");
else printf("0\n");
return ;
}
if(n==)
{
if((d[]==||d[]>)&&(d[]==||d[]>)) printf("1\n");
else printf("0\n");
return ;
}
if(flag)
{
printf("0\n");
return ;
}
for(int i=n--sum;i<=n-;i++)
ans=Mult(ans,i);
for(int i=;i<=n--sum;i++)
ans=Mult(ans,n-cnt);
for(int i=;i<=cnt;i++)
for(int j=;j<=d[i]-;j++)
ans=Div(ans,j);
Output(ans);
return ;
}
1005: [HNOI2008]明明的烦恼的更多相关文章
- BZOJ 1005 [HNOI2008] 明明的烦恼(组合数学 Purfer Sequence)
题目大意 自从明明学了树的结构,就对奇怪的树产生了兴趣...... 给出标号为 1 到 N 的点,以及某些点最终的度数,允许在任意两点间连线,可产生多少棵度数满足要求的树? Input 第一行为 N( ...
- BZOJ 1005: [HNOI2008]明明的烦恼 Purfer序列 大数
1005: [HNOI2008]明明的烦恼 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/ ...
- bzoj 1005: [HNOI2008]明明的烦恼 prufer编号&&生成树计数
1005: [HNOI2008]明明的烦恼 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 2248 Solved: 898[Submit][Statu ...
- BZOJ 1005: [HNOI2008]明明的烦恼( 组合数学 + 高精度 )
首先要知道一种prufer数列的东西...一个prufer数列和一颗树对应..然后树上一个点的度数-1是这个点在prufer数列中出现次数..这样就转成一个排列组合的问题了.算个可重集的排列数和组合数 ...
- 【BZOJ 1005】 1005: [HNOI2008]明明的烦恼 (prufer数列+高精度)
1005: [HNOI2008]明明的烦恼 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 4981 Solved: 1941 Description ...
- BZOJ 1005 [HNOI2008]明明的烦恼 (Prufer编码 + 组合数学 + 高精度)
1005: [HNOI2008]明明的烦恼 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 5786 Solved: 2263[Submit][Stat ...
- BZOJ 1005 [HNOI2008]明明的烦恼 purfer序列,排列组合
1005: [HNOI2008]明明的烦恼 Description 自从明明学了树的结构,就对奇怪的树产生了兴趣......给出标号为1到N的点,以及某些点最终的度数,允许在任意两点间连线,可产生多少 ...
- bzoj 1005 [HNOI2008] 明明的烦恼 (prufer编码)
[HNOI2008]明明的烦恼 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 5907 Solved: 2305[Submit][Status][Di ...
- BZOJ 1005: [HNOI2008]明明的烦恼(prufer数列)
http://www.lydsy.com/JudgeOnline/problem.php?id=1005 题意: Description 自从明明学了树的结构,就对奇怪的树产生了兴趣......给出标 ...
- 【BZOJ】1005: [HNOI2008]明明的烦恼(prufer编码+特殊的技巧)
http://www.lydsy.com/JudgeOnline/problem.php?id=1005 这里讲得挺清楚的:http://www.cnblogs.com/zhj5chengfeng/p ...
随机推荐
- 74th LeetCode Weekly Contest Valid Tic-Tac-Toe State
A Tic-Tac-Toe board is given as a string array board. Return True if and only if it is possible to r ...
- 1017 A除以B (20 分)
本题要求计算 /,其中 A 是不超过 1000 位的正整数,B 是 1 位正整数.你需要输出商数 Q 和余数 R,使得 A=B×Q+R成立. 输入格式: 输入在一行中依次给出 A 和 B,中间以 1 ...
- ProtobufUtils
import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Method; import com. ...
- jQuery树形控件zTree使用
http://www.cnblogs.com/AutumnRhyme/p/5915769.html .................................................. ...
- JD孔_20160912
1.买的 “航嘉(Huntkey)大白803 8位3米 总控开关 防过载保护 插座/排插/拖” http://item.jd.com/1786149.html#product-detail 2.
- postgresql备份数据库
备份数据库:pg_dump -U username -h localhost -f /me.sql 数据库名; 恢复数据库:psql -U username -h localhost -f /me.s ...
- Python 2.x和3.x不同点
1.print和print() 2.yield 出现下面的错误Traceback (most recent call last): File “<pyshell#32>”, line 1, ...
- (转)KICKSTART无人值守安装
KICKSTART无人值守安装 导言 作为中小公司的运维,经常会遇到一些机械式的重复工作,例如:有时公司同时上线几十甚至上百台服务器,而且需要我们在短时间内完成系统安装. 常规的办法有什么? 光盘安装 ...
- python多继承(新式类)一
最近在学习python的多重继承. 先来了解下多重继承的概念,所谓多重继承,是指python的类可以有两个以上父类,也即有类A,类B,类C,C同时继承类A与类B,此时C中可以使用A与B中的属性与方法. ...
- 编译64位geos库的经验总结
作者:朱金灿 来源:http://blog.csdn.net/clever101 使用CMake生成Win64的解决方案后,使用VS2010打开这个解决方案,然后 在"C/C++" ...