BZOJ 1005 明明的烦恼

时间:2023-03-08 21:51:34

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

利用Purfer Sequence,参见:http://www.cnblogs.com/zhj5chengfeng/archive/2013/08/23/3278557.html

 #include<cstring>
#include<cstdio>
#include<cstdlib>
using namespace std; #define maxn 1010
int d[maxn],n,sum,cnt,tot,prime[maxn],num[maxn];
bool exist[maxn];
struct node
{
int a[maxn*],len;
node(){memset(a,,sizeof(a)); len = ;}
friend inline node operator *(node &x,int y)
{
node z; z.len = x.len + ;
int i;
for (i = ;i <= z.len;++i)
{
z.a[i] += x.a[i] * y;
z.a[i+] += z.a[i] / ;
z.a[i] %= ;
}
while (!z.a[z.len]) --z.len;
return z;
} inline void print() {for (int i = len;i;--i) printf("%d",a[i]);}
}ans; inline void ready()
{
int i,j;
for (i = ;i <= ;++i)
if (!exist[i])
{
exist[i] = true;
prime[++tot] = i;
for (j = i*i;j <= ;j += i)
exist[j] = true;
}
} inline bool okay()
{
for (int i = ;i <= n;++i)
{
if (d[i] > ) sum += d[i] - ,++cnt;
if (d[i] == ) return false;
}
if (sum + n - cnt > *(n-)) return false;
if (cnt == n && sum != *(n-)) return false;
return true;
} inline void Div(int a,int bei)
{
if (a == ) return;
if (bei == ) return;
for (int i = ;i <= tot;++i)
{
if (a == ) break;
if (a % prime[i] == )
{
int t = ;
while (a % prime[i] == ) ++t,a /= prime[i];
num[i] += t * bei;
}
}
} inline void calc()
{
ready();
for (int i = ;i <= n-;++i) Div(i,);
Div(n - cnt,n-sum-);
for (int i = ;i <= n--sum;++i) Div(i,-);
for (int i = ;i <= n;++i) if (d[i] != -)
for (int j = ;j < d[i];++j) Div(j,-);
ans.a[] = ;
for (int i = ;i <= tot;++i)
for (int j = ;j <= num[i];++j)
ans = ans * prime[i];
ans.print();
} int main()
{
scanf("%d",&n); int i;
for (i = ;i <= n;++i) scanf("%d",d+i);
if (!okay()) printf("%d",);
else calc();
return ;
}