您的位置:首页 > Web前端

bzoj 1005 明明的烦恼 【Prufer序列】

2016-07-16 00:20 363 查看
啊啊啊啊,什么东西都堆到noi前几天来学真的是要完啊,关键是我还在浪啊TATAT

日常吐槽QwQ

题目大意:给定一棵树其中某些点的度数,求有多少种树满足要求

orz大爷的博客%%%

prufer序列

对于一棵树,每次选择编号最小的叶节点,删除它,并将与它相连的那个节点编号加入序列,直到只剩下两个节点为止

事实证明,树和prufer序列是一一对应的

性质:若一个点的度数为d,那么它将会在序列中出现d - 1次

然后就是组合数学啦23333

令 m = n−2−∑ki=1(di−1),num 为不确定度数的点的个数

ans = (n−2)!∑ki=1(di−1)!⋅m⋅numm

高精orz

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#define N 3000
using namespace std;

int n,len,m,tot,x;
int a
,ans
;

void mul(int x)
{
int r = 0;
for (int i = 0;i <= len;i ++)
{
ans[i] = ans[i] * x + r;
r = ans[i] / 10;
ans[i] %= 10;
}
for (;r;r /= 10) ans[++ len] = r % 10;
}

int main()
{
scanf("%d",&n),tot = n - 2;
for (int i = 1;i <= n;i ++)
{
scanf("%d",&x);
if (x == -1) m ++;
else if (x > 1)
{
for (int j = 2;j < x;j ++) a[j] --;
tot -= x - 1;
}
}
for (int i = 2;i <= n - 2;i ++) a[i] ++;
for (int i = 2;i <= tot;i ++) a[i] --;
a[m] += tot,ans[0] = 1;
for (int i = n;i >= 2;i --)
{
for (int j = 2;j * j <= i;j ++)
if (i % j == 0) {a[j] += a[i],a[i/j] += a[i],a[i] = 0;break;}
while (a[i] --) mul(i);
}
for (int i = len;i >= 0;i --) printf("%d",ans[i]);

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: