1005: [HNOI2008]明明的烦恼
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 4640 Solved: 1831
[ Submit][ Status][ Discuss]
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
Source
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<bitset>
#include<ext/pb_ds/priority_queue.hpp>
using namespace std;
const int maxn = 1010;
const int N = 334;
typedef long long LL;
const LL mo = 1000000000;
struct data{
LL a[N]; int len; data(){memset(a,0,sizeof(a)); len = 0;}
data operator + (const data &B)
{
data c; int Max = max(len,B.len);
for (int i = 0; i < Max; i++)
{
c.a[i] += a[i] + B.a[i];
c.a[i + 1] += c.a[i] / mo;
c.a[i] %= mo;
}
c.len = c.a[Max] ? Max + 1 : Max;
return c;
}
data operator * (const data &B)
{
data c;
for (int i = 0; i < len; i++)
for (int j = 0; j < B.len; j++)
{
c.a[i + j] += a[i] * B.a[j];
c.a[i + j + 1] += c.a[i + j] / mo;
c.a[i + j] %= mo;
}
c.len = c.a[len + B.len - 1] ? len + B.len : len + B.len - 1;
return c;
}
}Ans,C[2][maxn];
int n,m,tot,res,tp,cur,nex = 1,stk[maxn];
bool vis[maxn][maxn],bo[maxn][maxn];
void Print(int x,int k)
{
if (k == 9) {printf("%d",x); return;}
Print(x / 10,k + 1); printf("%d",x % 10);
}
data ksm()
{
data ret,x;
ret.a[0] = ret.len = 1;
x.a[0] = m; x.len = 1;
for (; res; res >>= 1)
{
if (res & 1) ret = ret * x;
x = x * x;
}
return ret;
}
int main()
{
#ifdef DMC
freopen("DMC.txt","r",stdin);
freopen("2.out","w",stdout);
#endif
cin >> n; res = tot = n - 2;
C[0][0].a[0] = Ans.a[0] = Ans.len = C[0][0].len = 1;
for (int i = 1; i <= n; i++)
{
int x; scanf("%d",&x);
if (x == -1) ++m;
else stk[++tp] = x - 1;
}
sort(stk + 1,stk + tp + 1);
for (int i = 1; i <= tp; i++)
{
vis[res][stk[i]] = bo[res][stk[i]] = 1;
res -= stk[i]; if (res < 0) {puts("0"); return 0;}
}
for (int i = tot; i; i--)
for (int j = 1; j <= i; j++)
if (bo[i][j]) bo[i][j] = bo[i-1][j] = bo[i-1][j-1] = 1;
for (int i = 1; i <= tot; i++,swap(cur,nex))
{
C[nex][0].a[0] = C[nex][0].len = 1;
for (int j = 1; j <= i; j++)
{
if (!bo[i][j]) continue;
C[nex][j] = C[cur][j] + C[cur][j - 1];
if (vis[i][j]) Ans = Ans * C[nex][j];
}
}
if (m) Ans = Ans * ksm();
cout << Ans.a[Ans.len - 1];
for (int i = Ans.len - 2; i >= 0; i--) Print(Ans.a[i],1);
puts("");
return 0;
}