数学问题 组合计数 树 prufer序列 高精度


Time Limit: 1 Sec  Memory Limit: 162 MB

Submit: 4948  Solved: 1926

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

 


Source

 

数学问题 组合数  高精度 树 prufer序列

利用一个prufer序列对应唯一的树结构这一性质,进行花式组合计算

为了回避麻烦的高精度除法,可以分解质因数,用减指数代替直接除,最后再把各质数乘起来。

答案蜜汁长,2000位高精度WA掉了,压了两位就过了。



1 #include<iostream>
2 #include<algorithm>
3 #include<cstring>
4 #include<cstdio>
5 #include<cmath>
6 using namespace std;
7 const int mxn=1010;
8 int read(){
9 int x=0,f=1;char ch=getchar();
10 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
11 while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
12 return x*f;
13 }
14 struct Num{
15 int x[2001],len;
16 void read(int a){
17 len=0;
18 while(a){x[++len]=a%100;a/=100;}
19 return;
20 }
21 inline int max(int a,int b){return a>b?a:b;}
22 void operator * (int b){
23 for(int i=1;i<=len;i++)
24 x[i]*=b;
25 for(int i=1;i<=len;i++)
26 if(x[i]>9){
27 x[i+1]+=x[i]/100;
28 x[i]%=100;
29 len=max(len,i+1);
30 }
31 return;
32 }
33 }a;
34 void Print(Num a){
35 while(!a.x[a.len])a.len--;
36 for(int i=a.len;i;i--)
37 if(i==a.len)printf("%d",a.x[i]);
38 else printf("%02d",a.x[i]);
39 puts("");
40 return;
41 }
42 int pri[mxn],cnt=0;
43 bool vis[mxn];
44 void init(){
45 for(int i=2;i<mxn;i++){
46 if(!vis[i])pri[++cnt]=i;
47 for(int j=1;j<=cnt && pri[j]*i<mxn;j++){
48 vis[pri[j]*i]=1;
49 if(i%pri[j]==0)break;
50 }
51 }
52 return;
53 }
54 int p[mxn],d[mxn],n,m,smm=0;
55 void calc(int x,int f){
56 // printf("calc:%d %d\n",x,f);
57 for(int i=1;i<=cnt && pri[i]<=x;i++){
58 while(x%pri[i]==0){
59 p[i]+=f;
60 x/=pri[i];
61 }
62 }
63 return;
64 }
65 int main(){
66 // freopen("bzoj_100511.in","r",stdin);
67 // freopen("bzoj_1005.out","w",stdout);
68 int i,j;
69 init();
70 n=read();
71 if(n==1){
72 i=read();
73 if(!i || i==-1)printf("1\n");
74 else printf("0\n");
75 return 0;
76 }
77 for(i=1;i<=n;i++){
78 d[i]=read();
79 if(!d[i]){
80 printf("0\n");return 0;
81 }
82 if(d[i]!=-1)smm+=d[i]-1;
83 else m++;
84 }
85 if(smm>n-2 || !m){
86 printf("0\n");return 0;
87 }
88 for(i=n-2;i>1;i--)calc(i,1);
89 calc(m,n-2-smm);
90 for(i=n-2-smm;i>1;i--)calc(i,-1);
91 for(i=1;i<=n;i++){
92 for(j=d[i]-1;j>1;j--){
93 calc(j,-1);
94 }
95 }
96 a.read(1);
97 for(i=1;i<=cnt;i++){
98 for(j=1;j<=p[i];j++)
99 a.operator *(pri[i]);
100 }
101 Print(a);
102 return 0;
103 }