bzoj1005: [HNOI2008]明明的烦恼(prufer+高精度)

1005: [HNOI2008]明明的烦恼

题目:传送门 

 

题解:

   毒瘤题啊天~

   其实思考的过程还是比较简单的。。。

   首先当然还是要了解好prufer序列的基本性质啦

   那么和1211大体一致,主要还是利用组合数学:

   首先我们把度数和-n记录为sum,那么根据prufer序列,序列的元素个数就是n-2

   那就是要在n-2个位置中选sum个,然后就是分别根据度数要求算每个元素在sum个位置中的方案,然后乘起来。最后还要乘上没有度数要求的元素的方案数就...ok啦

   思考两分钟...代码两小时...太菜啦!!!!

代码:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cstdlib>
 4 #include<cmath>
 5 #include<algorithm>
 6 #define qread(x) x=read()
 7 using namespace std;
 8 inline int read()
 9 {
10     int f=1,x=0;char ch;
11     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
12     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
13     return f*x;
14 }
15 struct node
16 {
17     int len,a[11000];
18     node(){memset(a,0,sizeof(a));}
19 }no,n1;
20 void chengfa(int x)
21 {
22     int i;
23     for(i=1;i<=no.len;i++)no.a[i]=no.a[i]*x;
24     for(i=1;i<=no.len;i++)
25     {
26         no.a[i+1]+=no.a[i]/10;
27         no.a[i]%=10;
28     }
29     i=no.len;
30     while(no.a[i+1]>0)
31     {
32         i++;
33         no.a[i+1]+=no.a[i]/10;
34         no.a[i]%=10;
35     }
36     no.len=i;
37     while(no.a[no.len]==0 && no.len>1)no.len--;
38 }
39 bool pd(int x)
40 {
41     if(x<2)return false;
42     double t=sqrt(double(x+1));
43     for(int i=2;i<=t;i++)
44         if(x%i==0)
45             return false;
46     return true;
47 }
48 int n,d[1100],pr[1100],s[1100];
49 int main()
50 {
51     scanf("%d",&n);int cnt=0,sum=0;
52     if(n==1){qread(d[1]);if(d[1]){printf("0\n");return 0;}else {printf("1\n");return 0;}}
53     for(int i=1;i<=n;i++)
54     {
55         qread(d[i]);
56         if(d[i]==0){printf("0\n");}
57         if(d[i]==-1)cnt++;
58         else d[i]-=1,sum+=d[i];
59     }
60     if(sum>n-2){printf("0\n");return 0;}
61     if(sum<n-2 && cnt==0){printf("0\n");return 0;}
62     int len=0;
63     for(int i=2;i<=n;i++)if(pd(i))pr[++len]=i;
64     for(int i=2;i<=n-2;i++)
65     {
66         int x=i;
67         for(int j=1;j<=len;j++)
68             while(x%pr[j]==0 && x!=0)
69                 s[j]++,x/=pr[j];
70     }
71     for(int i=2;i<=n-2-sum;i++)
72     {
73         int x=i;
74         for(int j=1;j<=len;j++)
75             while(x%pr[j]==0 && x!=0)
76                 s[j]--,x/=pr[j];
77     }
78     for(int i=1;i<=n;i++)
79         if(d[i]>0)
80         {
81             for(int k=2;k<=d[i];k++)
82             {
83                 int x=k;
84                 for(int j=1;j<=len;j++)
85                     while(x%pr[j]==0 && x!=0)
86                         s[j]--,x/=pr[j];
87             }
88         }
89     no.a[1]=1;no.len=1;
90     for(int i=1;i<=len;i++)
91         while(s[i]--)
92             chengfa(pr[i]);
93     for(int i=1;i<=n-2-sum;i++)chengfa(cnt);
94     for(int i=no.len;i>=1;i--)
95         printf("%d",no.a[i]);
96     printf("\n");
97     return 0;
98 }

 

   

 

posted @ 2018-01-23 15:42  CHerish_OI  阅读(183)  评论(0编辑  收藏  举报