【BZOJ 1005】[HNOI2008]明明的烦恼

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

 
数学相关
我觉得我是做不出来了,只能学一下关于暴力分解的各种咯
 1 #include<cstdio>
 2 #define mod 100000
 3 #include<cmath>
 4 using namespace std;
 5 int num[1001],ans[1001],pri[1001],d[1010];
 6 int cnt,n,l,m,tot;
 7 bool jud(int x){
 8      for(int i=2;i<=sqrt(x);i++)
 9          if(x%i==0)return 0;
10      return 1;
11 }
12  
13 void getpri(){
14      for(int i=2;i<=1000;i++)
15          if(jud(i))pri[++cnt]=i;
16 }
17  
18 void solve(int a,int f){
19     for(int i=2;i<=a;i++){
20         int x=i;
21         for(int j=1;j<=cnt;j++){
22             if(x==0) break;
23             while(x%pri[j]==0){
24                 num[j]+=f;x/=pri[j];
25             }
26         }
27     }
28 }
29  
30 void mult(int x){
31     for(int i=1;i<=l;i++) ans[i]*=x;
32     for(int i=1;i<=l;i++) ans[i+1]+=ans[i]/mod,ans[i]%=mod;
33     while(ans[l+1]>0){
34         l++;ans[l+1]=ans[l]/mod;ans[l]%=mod;
35     }
36 }
37 void print()
38 {
39     for(int i=l;i>0;i--)
40         if(i==l)printf("%d",ans[i]);
41         else printf("%05d",ans[i]);
42 }
43 int main(){
44     getpri();
45     int x;ans[1]=1;l=1;
46     scanf("%d",&n);
47     if(n==1){
48         scanf("%d",&x);
49         if(!x) {printf("1");return 0;}
50         else {printf("0");return 0;}
51     }
52     for(int i=1;i<=n;i++){
53         scanf("%d",&d[i]);
54         if(d[i]==0) {printf("0");return 0;}
55         if(d[i]==-1) m++;
56         else {d[i]--;tot+=d[i];} 
57     }
58     if(tot>n-2){printf("0");return 0;}
59     solve(n-2,1);solve(n-2-tot,-1);
60     for(int i=1;i<=n;i++) if(d[i]) solve(d[i],-1);
61     for(int i=1;i<=n-2-tot;i++) mult(m);
62     for(int i=1;i<=cnt;i++) while(num[i]--) mult(pri[i]);
63     print();
64 }

 

posted @ 2016-02-24 08:08  Alisahhh  阅读(176)  评论(0编辑  收藏  举报