BZOJ 1005 明明的烦恼
Description
自从明明学了树的结构,就对奇怪的树产生了兴趣...... 给出标号为1到N的点,以及某些点最终的度数,允许在任意两点间连线,可产生多少棵度数满足要求的树?
Input
第一行为N(0 < N < = 1000),接下来N行,第i+1行给出第i个节点的度数Di,如果对度数不要求,则输入-1
Output
一个整数,表示不同的满足要求的树的个数,无解输出0
Sample Input
3
1
-1
-1
1
-1
-1
Sample Output
2
HINT
两棵树分别为1-2-3;1-3-2
利用Purfer Sequence,参见:http://www.cnblogs.com/zhj5chengfeng/archive/2013/08/23/3278557.html
1 #include<cstring> 2 #include<cstdio> 3 #include<cstdlib> 4 using namespace std; 5 6 #define maxn 1010 7 int d[maxn],n,sum,cnt,tot,prime[maxn],num[maxn]; 8 bool exist[maxn]; 9 struct node 10 { 11 int a[maxn*10],len; 12 node(){memset(a,0,sizeof(a)); len = 1;} 13 friend inline node operator *(node &x,int y) 14 { 15 node z; z.len = x.len + 3; 16 int i; 17 for (i = 1;i <= z.len;++i) 18 { 19 z.a[i] += x.a[i] * y; 20 z.a[i+1] += z.a[i] / 10; 21 z.a[i] %= 10; 22 } 23 while (!z.a[z.len]) --z.len; 24 return z; 25 } 26 27 inline void print() {for (int i = len;i;--i) printf("%d",a[i]);} 28 }ans; 29 30 inline void ready() 31 { 32 int i,j; 33 for (i = 2;i <= 1000;++i) 34 if (!exist[i]) 35 { 36 exist[i] = true; 37 prime[++tot] = i; 38 for (j = i*i;j <= 1000;j += i) 39 exist[j] = true; 40 } 41 } 42 43 inline bool okay() 44 { 45 for (int i = 1;i <= n;++i) 46 { 47 if (d[i] > 0) sum += d[i] - 1,++cnt; 48 if (d[i] == 0) return false; 49 } 50 if (sum + n - cnt > 2*(n-1)) return false; 51 if (cnt == n && sum != 2*(n-1)) return false; 52 return true; 53 } 54 55 inline void Div(int a,int bei) 56 { 57 if (a == 0) return; 58 if (bei == 0) return; 59 for (int i = 1;i <= tot;++i) 60 { 61 if (a == 1) break; 62 if (a % prime[i] == 0) 63 { 64 int t = 0; 65 while (a % prime[i] == 0) ++t,a /= prime[i]; 66 num[i] += t * bei; 67 } 68 } 69 } 70 71 inline void calc() 72 { 73 ready(); 74 for (int i = 1;i <= n-2;++i) Div(i,1); 75 Div(n - cnt,n-sum-2); 76 for (int i = 1;i <= n-2-sum;++i) Div(i,-1); 77 for (int i = 1;i <= n;++i) if (d[i] != -1) 78 for (int j = 1;j < d[i];++j) Div(j,-1); 79 ans.a[1] = 1; 80 for (int i = 1;i <= tot;++i) 81 for (int j = 1;j <= num[i];++j) 82 ans = ans * prime[i]; 83 ans.print(); 84 } 85 86 int main() 87 { 88 scanf("%d",&n); int i; 89 for (i = 1;i <= n;++i) scanf("%d",d+i); 90 if (!okay()) printf("%d",0); 91 else calc(); 92 return 0; 93 }
高考结束,重新回归。