zoukankan      html  css  js  c++  java
  • BZOJ 1005: [HNOI2008]明明的烦恼( 组合数学 + 高精度 )

    首先要知道一种prufer数列的东西...一个prufer数列和一颗树对应..然后树上一个点的度数-1是这个点在prufer数列中出现次数..这样就转成一个排列组合的问题了。算个可重集的排列数和组合数就行了...要写高精..

    ---------------------------------------------------------------------

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
     
    using namespace std;
     
    const int maxn = 1009;
     
    int deg[maxn], N, m, c;
    int p[maxn], pn;
    int cnt[maxn];
    bool F[maxn];
     
    void Init() {
    m = 0;
    scanf("%d", &N);
    for(int i = 0; i < N; i++) {
    scanf("%d", deg + i);
    if(~deg[i])
    m++, c += deg[i] - 1;
    }
    pn = 0;
    memset(F, 0, sizeof F);
    for(int i = 2; i <= N; i++) {
    if(!F[i])
    p[pn++] = i;
    for(int j = 0; j < pn && i * p[j] <= N; j++) {
    F[i * p[j]] = true;
    if(i % p[j] == 0) break;
    }
    }
    }
     
    void Work(int V, bool t) {
    for(int x = 2; x <= V; x++ )
    for(int i = 0, v = x; i < pn && v != 1; i++)
    for(; v % p[i] == 0; v /= p[i], t ? cnt[i]++ : cnt[i]--);
    }
     
    struct BigInt {
    static const int MAXN = 10000;
    static const int BASE = 10000;
    static const int WID = 4;
    int s[MAXN], n;
    BigInt(int _n = 0) : n(_n) {
    memset(s, 0, sizeof s);
    }
    BigInt operator = (int num) {
    for(; num; s[n++] = num % BASE, num /= BASE);
    return *this;
    }
    BigInt operator *= (const int &x) {
    for(int i = 0; i < n; i++) s[i] *= x;
    for(int i = 0; i < n; i++) if(s[i] >= BASE) {
    s[i + 1] += s[i] / BASE;
    s[i] %= BASE;
    }
    if(s[n]) n++;
    return *this;
    }
    void WRITE() {
    int buf[8], t;
    for(int i = n; i--; ) {
    t = 0;
    for(int v = s[i]; v; buf[t++] = v % 10, v /= 10);
    if(i + 1 != n) {
    for(int j = WID - t; j; j--)
    putchar('0');
    }
    while(t--)
    putchar(buf[t] + '0');
    }
    }
    };
     
    int main() {
    Init();
    if(c > N - 2) {
    puts("0"); return 0;
    }
    memset(cnt, 0, sizeof cnt);
    for(int i = 0, v = N - m; i < pn && v != 1; i++)
    for(; v % p[i] == 0; v /= p[i], cnt[i]++);
    for(int i = 0, t = N - 2 - c; i < pn; i++) 
    if(cnt[i] > 0) cnt[i] *= t;
    Work(N - 2, 1);
    Work(N - c - 2, 0);
    for(int i = 0; i < N; i++)
    if(~deg[i]) Work(deg[i] - 1, 0);
    BigInt ans; ans = 1;
    for(int i = 0; i < pn; i++)
    for(; cnt[i]--; ans *= p[i]);
    ans.WRITE();
    return 0;
    }

    --------------------------------------------------------------------- 

    1005: [HNOI2008]明明的烦恼

    Time Limit: 1 Sec  Memory Limit: 162 MB
    Submit: 3412  Solved: 1358
    [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

    Sample Output

    2

    HINT

    两棵树分别为1-2-3;1-3-2

    Source

  • 相关阅读:
    ubuntu给手机建wifi
    UTF-8编码的字符串拆分成单字、获取UTF-8字符串的字符个数的代码及原理(c++实现)
    Android 获取WIFI MAC地址的方法
    【美妙的Python之二】Python初步
    LCD深度剖析
    Eclipse断点调试
    Draw2d中的布局管理器Layout比较
    Java实现 蓝桥杯VIP 算法训练 输出米字形
    Java实现 蓝桥杯VIP 算法训练 输出米字形
    Java实现 蓝桥杯VIP 算法训练 斜率计算
  • 原文地址:https://www.cnblogs.com/JSZX11556/p/5008204.html
Copyright © 2011-2022 走看看