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

  • 相关阅读:
    【Language】 TIOBE Programming Community Index for February 2013
    【diary】good health, good code
    【web】a little bug of cnblog
    【Git】git bush 常用命令
    【web】Baidu zone ,let the world know you
    【diary】help others ,help yourself ,coding is happiness
    【Git】Chinese messy code in widows git log
    【windows】add some font into computer
    SqlServer启动参数配置
    关于sqlserver中xml数据的操作
  • 原文地址:https://www.cnblogs.com/JSZX11556/p/5008204.html
Copyright © 2011-2022 走看看