[HNOI2008]明明的烦恼

根据prufer序列可以一一对应无根树。

一个度数为\(n\)的会出现\(n - 1\)次,然后组合数算一算就好了。

注意高精度

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
 
int n, t;
const int MAXN = 5010;
typedef long long LL;
const int DX = 1000000;
struct N {
    int sum[MAXN], dig;
    void mul(int x) {
        for (int i = 0; i != dig; ++i) sum[i] *= x;
        for (int i = 0; i != dig + 5; ++i) {
            sum[i + 1] += sum[i] / DX;
            sum[i] %= DX;
        }
        dig += 5;
        while (!sum[dig - 1]) --dig;
    }
    void div(int x) {
        int now = 0;
        for (int i = dig - 1; ~i; --i) {
            now = now * DX + sum[i];
            sum[i] = now / x;
            now %= x;
        }
        while (!sum[dig - 1]) --dig;
    }
    void print() {
        printf("%d", sum[dig - 1]);
        for (int i = dig - 2; ~i; --i)
            printf("%06d", sum[i]);
        putchar(10);
    }
} a;
int main() {
    scanf("%d", &n);
    a.sum[0] = 1; a.dig = 1;
    for (int i = 2; i <= n - 2; ++i)
        a.mul(i);
    int lst = n - 2, cnt = 0;
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &t);
        cnt += t == -1;
        if (t < 0) continue;
        lst -= t - 1;
        for (int j = t - 1; j > 1; --j)
            a.div(j);
    }
    if (lst < 0 || (cnt == 0 && lst != 0)) return puts("0"), 0;
    for (int i = 1; i <= lst; ++i) a.mul(cnt), a.div(i);
    a.print();
    return 0;
}
posted @ 2019-02-11 13:08  daklqw  阅读(177)  评论(0编辑  收藏  举报